【复制粘贴即可运行】用Python制作一个简单的待-办事项列表应用!(基于文本)
要在电脑上通过命令提示符或 PowerShell 运行 Python,需要先下载并安装 Python。
如果你还没有安装,请参考Python安装与开发环境配置一文来完成安装。
你好!几个月前我还是个编程小白,现在我将分享我与AI一同搭建网站时学到的东西。
这次,我们将用Python制作一个“待办事项列表应用”,我非常推荐将其作为编程学习的第一步。本文的目标只有一个!就是让你体验到“我自己写的程序成功运行了!”的激动之情。
我们先把复杂的理论放一边!首先,让我们通过接触可以复制粘贴就能运行的代码,来实际感受“原来是这样运行的啊!”。文中的专业术语,我会根据自己曾遇到的困难,用最通俗易懂的方式进行讲解,请放心吧。
首先,让我们来运行一下成品吧!
事实胜于雄辩!让我们先来运行一下最终版的待办事项列表应用吧。请将下面的代码全部复制,创建一个名为todo.py的文件,然后粘贴并保存。
# -*- coding: utf-8 -*-
TASKS_FILE = "tasks.txt"
def load_tasks():
"""从文件读取任务的函数"""
try:
with open(TASKS_FILE, "r", encoding="utf-8") as f:
# 使用strip()移除每行末尾的换行符
tasks = [line.strip() for line in f.readlines()]
except FileNotFoundError:
# 如果文件不存在,则返回一个空列表
tasks = []
return tasks
def save_tasks(tasks):
"""将任务保存到文件的函数"""
with open(TASKS_FILE, "w", encoding="utf-8") as f:
# 在每个任务末尾添加换行符后写入
for task in tasks:
f.write(task + "\n")
def list_tasks(tasks):
"""显示任务列表的函数"""
if not tasks:
print("✅ 还没有任务。")
return
print("--- 待办事项列表 ---")
# 使用enumerate同时获取索引(序号)和任务
for i, task in enumerate(tasks):
print(f"{i + 1}: {task}")
print("------------------")
def add_task(tasks):
"""添加任务的函数"""
task = input("请输入要添加的任务:")
if task:
tasks.append(task)
save_tasks(tasks)
print(f"✨ 任务 “{task}” 已添加。")
else:
print("⚠️ 未输入任务。")
def delete_task(tasks):
"""删除任务的函数"""
list_tasks(tasks)
if not tasks:
return
try:
# 让用户通过编号选择任务
num_str = input("请输入要删除的任务编号:")
num = int(num_str)
# 用户从1开始计数,但列表索引从0开始,因此需要调整
if 1 <= num <= len(tasks):
removed_task = tasks.pop(num - 1)
save_tasks(tasks)
print(f"🗑️ 任务 “{removed_task}” 已删除。")
else:
print("⚠️ 该编号的任务不存在。")
except ValueError:
# 输入非数字时的错误处理
print("⚠️ 请正确输入编号。")
def main():
"""执行主处理的函数"""
tasks = load_tasks()
while True:
print("\n要做什么?")
command = input("1:显示列表, 2:添加, 3:删除, 9:退出 > ")
if command == "1":
list_tasks(tasks)
elif command == "2":
add_task(tasks)
elif command == "3":
delete_task(tasks)
elif command == "9":
print("👋 退出应用。辛苦了!")
break
else:
print("⚠️ 请输入 1, 2, 3, 或 9。")
if __name__ == "__main__":
main()
保存后,打开终端(在Windows上是命令提示符或PowerShell),进入到保存文件的目录,然后运行以下命令。
python todo.py
怎么样?它问你“要做什么?”了吗? 试试输入“2”来添加任务,输入“1”来查看列表,或者输入“3”来删除任务。输入“9”可以退出应用。太棒了,这已经是一个功能齐全的应用了!
接下来,让我们一起来揭开这些魔法咒语(代码)的神秘面纱吧。
步骤1:只有“添加”和“显示列表”功能的超简化版
想一次性理解所有内容是很困难的。让我们从一个更简单的代码版本开始,只关注应用的核心部分——“添加任务”和“显示列表”功能。
# 准备一个空列表(类似于数组)来保存任务
tasks = []
# 无限循环处理
while True:
print("\n要做什么?")
command = input("1:显示列表, 2:添加, 9:退出 > ")
if command == "1":
print("--- 待办事项列表 ---")
for task in tasks:
print(task)
print("------------------")
elif command == "2":
task = input("请输入要添加的任务:")
tasks.append(task)
print(f"✨ 任务 “{task}” 已添加。")
elif command == "9":
print("👋 退出应用。")
break # 退出循环
else:
print("⚠️ 请输入 1, 2, 或 9。")
这段简短的代码浓缩了编程的基础知识。
tasks = []: 这是用来存储任务的“列表”。可以想象成一开始准备一个空箱子。while True:: 这是一个“无限循环”。在输入“9”之前,它会一直等待用户的命令。这是我最初问AI“如何让程序一直处于等待状态?”时,它教给我的魔法咒语。input(...): 接收用户通过键盘输入的字符。if / elif / else: 根据输入的command的值来区分处理。这是一个条件分支,意思是“如果是1就显示列表,如果是2就添加,否则...”tasks.append(task): 将通过input接收到的任务添加到tasks列表的末尾。for task in tasks:: 从tasks列表中逐个取出内容,放到名为task的变量中,然后用print(task)显示在屏幕上。break: 这是结束无限循环的“逃生开关”。如果忘了加这个,程序就只能被强制终止了(我也经常犯这个错误!)。
步骤2:添加“删除功能”和“错误处理”
接下来,让我们实现删除已添加任务的功能。为了方便起见,我们将允许用户通过编号来选择要删除的任务。这里会稍微提高一点难度哦!
# ... (将步骤1代码中的 `if command == "1":` 部分替换为以下内容) ...
if command == "1":
print("--- 待办事项列表 ---")
# 使用 enumerate 可以同时获取列表的编号和内容
for i, task in enumerate(tasks):
# i 从0开始,所以显示时要加1
print(f"{i + 1}: {task}")
print("------------------")
# ... (在步骤1代码的 `elif command == "2":` 之后添加以下内容) ...
elif command == "3": # 添加删除功能
# 先显示当前列表,方便用户选择
for i, task in enumerate(tasks):
print(f"{i + 1}: {task}")
try:
num_str = input("请输入要删除的任务编号:")
num = int(num_str) # 将输入的字符串转换为数字
# 使用 pop() 按指定的编号(索引)从列表中删除元素
removed_task = tasks.pop(num - 1)
print(f"🗑️ 任务 “{removed_task}” 已删除。")
except ValueError:
print("⚠️ 请正确输入编号。")
except IndexError:
print("⚠️ 该编号的任务不存在。")
这里出现了一些新的知识点。
enumerate(tasks): 这个功能非常方便!在遍历列表时,它会自动为每个元素分配一个从“0, 1, 2...”开始的编号。这样我们就能像f"{i + 1}: {task}"这样,带编号地显示任务了。tasks.pop(num - 1): 这是删除操作的关键。pop()会从列表中移除指定位置的元素。之所以是num - 1,是因为用户输入的是“1”,但在程序世界(列表索引)中是从“0”开始计数的,所以需要向前调整一位。这个“从0开始”是编程新手肯定会混淆的地方,所以一定要记住!try / except: 这是错误处理机制。它的意思是“先尝试执行try:中的代码,如果出现错误,就用except:捕捉它,然后执行这里的处理,而不是让程序崩溃”。ValueError:int()用于将字符串转换为数字,但如果输入的字符串无法转换为数字(比如“啊”),就会出现这个错误。IndexError: 当你尝试用pop()删除一个列表中不存在的编号时(例如,列表里只有3个任务,你却要删除“5”),就会出现这个错误。
“用户的操作总会超出开发者的预想”这是一条铁律。加入这样的错误处理,可以防止应用意外崩溃,让程序变得更友好、更健壮。
步骤3:将数据保存到文件,防止数据丢失
我们现在的应用有一个很大的缺点。一旦程序关闭,所有添加的任务都会消失。这样就不能当作待办事项列表来用了,对吧?所以,我们要添加一个功能,将任务保存到文件中,并在下次启动时读取进来。
# 预先设定好文件名
TASKS_FILE = "tasks.txt"
# --- 函数定义 ---
def load_tasks():
try:
# "r" 是读取(read)模式
with open(TASKS_FILE, "r", encoding="utf-8") as f:
# 用readlines()读取所有行到列表中,并用strip()移除换行符
tasks = [line.strip() for line in f.readlines()]
except FileNotFoundError:
# 第一次运行时文件不存在会报错,所以返回一个空列表
tasks = []
return tasks
def save_tasks(tasks):
# "w" 是写入(write)模式。如果文件不存在,会自动创建
with open(TASKS_FILE, "w", encoding="utf-8") as f:
for task in tasks:
# 写入文件时,在每个任务的末尾加上换行符(\n)
f.write(task + "\n")
# --- 主处理 ---
# 应用启动时,首先从文件读取任务
tasks = load_tasks()
# 每次添加或删除任务时,修改代码以调用 save_tasks(tasks)
# (请参考开头的完整代码)
这里的要点是“文件的读写”。
with open(...) as f:: 这是Python中处理文件的经典写法。这样写可以在文件读写结束后自动关闭文件,非常安全。“我曾问AI‘如何安全地处理Python文件?’,它第一个推荐的就是这个。”- 模式 ("r", "w"):
open()的第二个参数用来指定打开文件的方式。"r"是只读(Read),"w"是只写(Write)。需要注意的是,"w"模式在文件已存在的情况下,会清空所有内容再进行写入。 encoding="utf-8": 请把这个当作一个“おまじない(咒语)”。为了正确处理像中文这样的多字节字符,这是必需的,不指定的话可能会导致乱码。- 读取 (load):
f.readlines()会将文件的内容按行读取到一个列表中。但每行的末尾都会包含一个换行符(\n),所以我们用line.strip()来移除它,得到干净的数据。 - 写入 (save):
f.write()用来向文件写入字符串。这次反过来,我们希望将每个任务保存为单独的一行,所以在任务字符串的末尾加上换行符\n。如果忘了加,所有的任务都会连成一行,导致无法正确读取(我自己也曾被这个问题困扰了15分钟...)。
最后,就像文章开头介绍的完整代码那样,将功能块用def封装成“函数”(这被称为重构),能让代码变得更清晰,更容易理解哪部分在做什么。当代码越来越长时,养成按功能将代码分门别类地装进“盒子”(函数)里的习惯,会让你未来的自己轻松很多。
总结:能跑起来就是胜利!然后迈向下一步
辛苦了!现在你已经掌握了用Python制作自己专属的待办事项列表应用的能力。最重要的是,“先别管完不完美,复制粘贴也行,先让它跑起来”,这比完全理解更重要。我亲身体会到,拥有一个能运行的东西,然后一点点地修改它,尝试“改变这里会怎么样?”,是进步最快的捷径。
错误并不可怕,它是让你程序变得更好的提示。即使看不懂错误信息,也可以直接把它复制粘贴问AI:“这个错误是什么意思,怎么修复?”,通常都能得到解决方案。
请务必尝试为你这次制作的应用添加“编辑任务功能”或“标记已完成任务功能”,把它培养成你独一无二的最强待办事项列表吧!