第十九课:你的第一个小程序 – 综合项目实战 (简易通讯录)
- 时长: 90 分钟
- 教学目标:
- 综合运用学过的所有核心知识:变量、数据类型、列表、字典、函数、循环、条件判断、文件操作、错误处理。
- 学习分析一个完整的应用需求,并将其分解为更小的功能模块。
- 练习使用函数来组织不同的功能代码,使程序结构清晰。
- 练习使用字典来存储有关联的数据(姓名和电话号码)。
- 练习使用文件操作来保存和加载数据,让信息不会丢失。
- 练习使用错误处理来提高程序的健壮性,应对用户输入错误或文件不存在等情况。
- 提升独立分析问题和编写完整应用程序的能力。
- 体验从零开始构建一个实际应用的过程和乐趣。
课程内容
1. 复习与引入 (10 分钟)
- 复习: 快速回顾:函数的作用(打包代码)、列表(有序)、字典(键值对)、文件操作(读写保存)、错误处理(
try...except
)。 - 提出问题: 老师提问:“我们已经学会了这么多编程技巧。如果现在我想写一个程序,能帮我记住朋友们的名字和电话号码,并且下次打开程序时,之前记下的信息还在,不会丢失,该怎么做呢?这个程序应该能添加新朋友,能查找某个朋友的电话,还能显示所有朋友的列表。”
- 引出综合项目: 这就是一个小型应用程序的例子。它需要存储数据、进行各种操作,还需要把数据保存到硬盘上。解决这样的问题,就需要把我们之前学过的所有知识都综合起来运用。今天,我们就来一起完成一个“简易通讯录”小程序。
2. 项目需求分析与功能分解 (15 分钟)
- 明确目标: 开发一个能存储姓名和电话号码,并支持添加、查找、显示、保存、加载功能的简易通讯录程序。
- 数据结构选择: 如何存储姓名和电话号码?姓名是唯一的,电话号码与姓名关联。用字典最合适!键是姓名,值是电话号码。整个通讯录就是这个字典。
# 我们的通讯录就存放在这个字典里 # 例如: contacts = {"小明": "13812345678", "小红": "13987654321"} contacts = {} # 程序开始时,通讯录通常是空的,或者从文件加载
- 功能分解: 程序需要提供哪些操作?
- 加载数据: 启动时从文件读取之前保存的联系人信息。
- 添加联系人: 获取姓名和号码,存到字典里。
- 查找联系人: 获取姓名,从字典里查找并显示号码。
- 显示所有联系人: 遍历字典,打印所有姓名和号码。
- 保存数据: 将字典里的联系人信息写到文件里。
- 主菜单: 显示操作选项,根据用户输入调用相应的功能。
- 退出程序: 停止运行。
- 函数设计: 为每个功能编写一个独立的函数,让代码更整洁、易读。
load_contacts(filename)
: 从文件加载数据,返回一个字典。save_contacts(contacts, filename)
: 将字典数据保存到文件。add_contact(contacts)
: 添加新的联系人。find_contact(contacts)
: 查找联系人。list_contacts(contacts)
: 显示所有联系人。main_menu()
: 显示菜单,获取用户选择,调用其他函数,控制程序运行流程。
- 文件选择: 数据保存到哪个文件?可以约定一个文件名,比如
contacts.txt
。文件格式可以简单约定,比如每行是一个联系人,姓名和号码之间用逗号分隔:姓名,电话\n
。
3. Step by Step 实现项目代码 (40 分钟)
老师带领学生一步一步编写代码。每实现一个函数,都进行简单的测试。
- 第一步:程序框架和主菜单
main_menu()
# 约定保存数据的文件名 CONTACT_FILE = "contacts.txt" # 主程序入口函数 def main_menu(): # 1. 启动时加载数据 contact_book = load_contacts(CONTACT_FILE) print("通讯录已加载。") # 2. 进入主循环 while True: print("\n--- 通讯录菜单 ---") print("1. 添加联系人") print("2. 查找联系人") print("3. 显示所有联系人") print("4. 保存通讯录") print("5. 退出") print("-" * 20) choice = input("请输入你的选择 (1-5): ") # 3. 根据用户选择调用不同的功能 if choice == '1': add_contact(contact_book) elif choice == '2': find_contact(contact_book) elif choice == '3': list_contacts(contact_book) elif choice == '4': save_contacts(contact_book, CONTACT_FILE) print("通讯录已保存到文件。") elif choice == '5': print("正在退出通讯录...") save_contacts(contact_book, CONTACT_FILE) # 退出前保存一次 print("通讯录已保存并安全退出。") break # 退出 while 循环,程序结束 else: print("无效的选择,请重新输入。") # 在程序的最下面,调用主菜单函数启动程序 # if __name__ == "__main__": # 这句话的意思是:如果当前文件是主程序,就执行下面的代码 # 这样写是为了防止这个文件被当作模块导入时,main_menu() 被意外执行 main_menu()
(讲解主循环
while True
,菜单打印,用户输入,if-elif-else
分支,break
退出循环。先只写框架,功能函数后面再实现) -
第二步:加载联系人
load_contacts()
# 加载联系人函数 def load_contacts(filename): contacts = {} # 初始化一个空的字典来存放联系人 try: # 尝试以读取模式打开文件 with open(filename, 'r', encoding='utf-8') as f: # 逐行读取文件内容 for line in f: # 去掉行末的空白字符(包括换行符) line = line.strip() # 如果这一行不是空的 if line: # 按逗号分割姓名和电话 parts = line.split(',') # 确保分割后至少有两部分 (姓名和电话) if len(parts) >= 2: name = parts[0] phone = parts[1] contacts[name] = phone # 存储到字典中 print(f"加载联系人: {name} - {phone}") # 可选,加载时打印提示 except FileNotFoundError: # 如果文件不存在,这是第一次运行,打印提示,返回空字典 print(f"文件 {filename} 未找到,将创建一个新的通讯录。") except Exception as e: # 捕捉其他可能的错误 print(f"加载文件时发生错误: {e}") return contacts # 返回加载好的通讯录字典
(讲解
with open('r')
和try...except FileNotFoundError
,文件逐行遍历,.strip()
清除空白,.split(',')
分割字符串,以及如何存入字典。强调错误处理。) -
第三步:保存联系人
save_contacts()
# 保存联系人函数 def save_contacts(contacts, filename): try: # 尝试以写入模式打开文件 (会清空原有内容再写入) with open(filename, 'w', encoding='utf-8') as f: # 遍历通讯录字典的键值对 for name, phone in contacts.items(): # 将每个联系人格式化成 "姓名,电话" 的字符串,并加上换行符 line = f"{name},{phone}\n" f.write(line) # 写入文件 except Exception as e: # 捕捉写入时可能发生的错误 print(f"保存文件时发生错误: {e}")
(讲解
with open('w')
,遍历字典的.items()
,f-string 格式化字符串,手动加\n
,以及错误处理。) -
第四步:添加联系人
add_contact()
# 添加联系人函数 def add_contact(contacts): print("\n--- 添加新的联系人 ---") name = input("请输入姓名: ") # 可以加一个简单的判断,姓名不能为空 if not name: print("姓名不能为空!") return # 结束函数 phone = input("请输入电话号码: ") # 可以加一个简单的判断,电话号码不能为空 if not phone: print("电话号码不能为空!") return # 结束函数 # 检查姓名是否已经存在 (可选) if name in contacts: print(f"联系人 {name} 已经存在,号码是 {contacts[name]}。") overwrite_choice = input("是否覆盖原有号码?(y/n): ").lower() if overwrite_choice != 'y': print("取消添加。") return # 结束函数 # 将新的键值对添加到字典中 contacts[name] = phone print(f"联系人 {name} 已添加/更新成功!")
(讲解如何获取用户输入,如何添加到字典。可以引入简单的输入验证和覆盖检查。)
-
第五步:查找联系人
find_contact()
# 查找联系人函数 def find_contact(contacts): print("\n--- 查找联系人 ---") name_to_find = input("请输入要查找的姓名: ") # 使用 .get() 方法安全地查找,如果找不到返回 None phone_number = contacts.get(name_to_find) if phone_number is not None: # 如果 .get() 返回的不是 None,说明找到了 print(f"找到联系人:{name_to_find} 的电话是 {phone_number}") else: # 如果 .get() 返回 None,说明没找到 print(f"抱歉,通讯录中没有找到联系人:{name_to_find}")
(讲解如何获取用户输入,如何使用
.get()
安全查找,以及根据查找结果(是否为None
)使用if-else
打印不同信息。) -
第六步:显示所有联系人
list_contacts()
# 显示所有联系人函数 def list_contacts(contacts): print("\n--- 所有联系人 ---") # 检查字典是否为空 if not contacts: # 或者 len(contacts) == 0 print("通讯录是空的。") return # 结束函数 # 遍历字典的键值对并打印 for name, phone in contacts.items(): print(f"姓名: {name}, 电话: {phone}") print("-" * 20) # 打印分隔线
(讲解如何检查字典是否为空,以及如何遍历字典的
.items()
并打印键值对。)
4. 整合、测试与完善 (10 分钟)
- 回顾整体结构: 再次展示完整的代码结构,强调函数之间的调用关系(
main_menu
调用其他功能函数,main_menu
启动程序)。 - 测试: 带领学生一起运行完整的程序,进行各种测试:
- 第一次运行程序(文件不存在)。
- 添加几个联系人。
- 显示所有联系人。
- 查找存在的联系人和不存在的联系人。
- 保存通讯录。
- 退出程序。
- 再次运行程序,检查之前保存的联系人是否被加载。
- 尝试输入无效的菜单选项。
- (如果时间允许)尝试手动修改
contacts.txt
文件,比如删除一行或添加一行格式错误的,再运行程序看加载是否出错(如果加了错误处理的话)。
- 完善: 根据测试中发现的问题进行简单调整(比如提示信息更友好,增加输入验证等)。
5. 总结与提问 (5 分钟)
- 回顾: 总结本节课完成了一个简单的通讯录小程序。回顾在项目中综合运用了哪些编程概念(列表、字典、函数、循环、条件、文件、错误处理)。强调了分解问题、函数封装、数据持久化的重要性。
- 提问:
- 我们为什么选择用字典来存储联系人?
- 哪个函数负责把数据保存到文件?哪个函数负责从文件加载?
- 在加载文件时,我们使用了
try...except
来处理什么错误? - 主菜单的循环是什么类型的循环?为什么用它?
- 如果我想删除一个联系人,应该修改哪个函数?
- 答疑: 回答学生问题。
6. 布置课后作业 (5 分钟)
- 作业 1: 在课堂完成的通讯录程序基础上,添加一个“删除联系人”的功能(在主菜单中增加一个选项,并编写相应的函数
delete_contact(contacts)
)。这个函数需要询问用户要删除的姓名,然后在字典中使用del contacts[姓名]
或.pop(姓名)
进行删除,并考虑姓名不存在的情况(使用in
检查或try...except KeyError
)。 - 作业 2: 扩展“查找联系人”功能,除了根据姓名查找,还可以根据电话号码反向查找姓名(这可能需要遍历字典的所有键值对)。
- 作业 3: (选做) 修改文件保存格式,比如使用 JSON 格式(简单介绍
import json
模块的json.dump()
和json.load()
),让数据保存和加载更规范。 - 作业 4: (选做) 统计通讯录中有多少个联系人,并在主菜单中显示总数。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)