实例2:通讯录
通讯录是存储联系人信息的名录。本实例要求编写通讯录程序,该程序可接收用户输入的姓名、电话、QQ号码、邮箱等信息,将这些信息保存到“通讯录.txt”文件中,实现新建联系人功能;可根据用户输入的联系人姓名查找联系人,展示联系人的姓名、电话、QQ号码、邮箱等信息,实现查询联系人功能。
实例目标
- 掌握文件的打开与关闭
- 掌握文件的读写
实例分析
从前面有关实例的描述可知,我们可将通讯录视为一个对象,该对象具有新建联系人和查询联系人的功能,另外为了让用户能按照提示操作,该对象中还应具有向用户展示操作菜单的功能。因此,这里定义一个表示通讯录的类TelephoneBook,通讯录中包含功能都可以抽象如下方法:
- show_menu():向用户展示操作界面及指令。
- add_info():新建联系人。
- show_info():查找联系人。
- main():系统流程。
以上方法中,add_info()实现新建联系人的功能,该方法会将用户输入的联系人信息保存到“通讯录.txt”文件中,相当于向文件中写数据的操作;show_info()实现查找联系人的功能,该方法会将用户输入的姓名与“通讯录.txt”文件中读取的数据进行比对,找到则返回该联系人的所有信息,否则就返回“联系人不存在”,相当于从文件中读取数据的操作。
代码实现
(1)创建一个address_book. py文件,在该文件中定义一个TelephoneBook类,并在该类中定义show_menu()函数,实现该函数比较简单,具体代码如下。
import sys
import json
class TelephoneBook:
def show_menu(self): # 用于展示功能菜单
print("*" * 20)
print("欢迎使用[通讯录] V1.0")
print("1. 新建联系人")
print("2. 查询联系人")
print("0. 退出系统")
print("*" * 20)
(2)在TelephoneBook类中定义add_info()方法。add_info()方法实现新建联系人的功能,该方法中需接收用户输入的信息,并暂时将这些信息保存到字典中。为了能持久化存储联系人信息,可将这些信息先转换为字符串类型,之后便调用write()方法写入到“通讯录.txt”文件中,具体代码如下。
def add_info(self):
name_str = input("请输入姓名:")
phone_num = input("请输入电话:")
qq_num = input("请输入QQ号码:")
mail_adr = input("请输入邮箱:")
# 将数据封装到字典中
card_dict = {"姓名": name_str, "手机号": phone_num,
"qq": qq_num, "mail": mail_adr}
f = open("通讯录.txt", mode='a+', encoding='utf-8')
# 将字典转换为str,然后再使用write()写入到通讯录的文本文件中
f.write(str(card_dict) + '\n')
f.close()
print(f"成功添加{name_str}为联系人")
(3)在TelephoneBook类中定义show_info ()方法。show_info ()方法实现查找联系人的功能,该方法中需读取“通讯录.txt”文件中的数据,该文件中若是有数据就直接读取,并将读取的数据与用户输入的数据进行比对,相同则返回联系人的信息,不同则返回“联系人不存在”,具体代码如下。
# 显示联系人信息
def show_info(self):
file = open("通讯录.txt", mode='r', encoding='utf-8')
# 如果通讯录.txt文件不为空时,执行下面代码
if len(file.read()) != 0:
# 保证每次从开始位置读取
file.seek(0, 0)
# 读取通讯录.txt文件中的内容
file_data = file.read()
# 对字符串进行分隔
split_info = file_data.split('\n')
# 删除多余的字符串
split_info.remove(split_info[len(split_info) - 1])
name = input("请输入要查询的姓名:")
name_li = [] # 用于存储联系人姓名的列表
all_info_li = [] # 用于存储所有联系人信息的列表
for i in split_info:
# 将单引号替换为双引号
dict_info = json.loads(i.replace("\'", '\"'))
all_info_li.append(dict_info)
# 获取所有联系人的姓名
name_li.append(dict_info['姓名'])
if name in name_li:
for person_info in all_info_li:
for title_key, name_value in person_info.items():
if name_value == name:
for title, info_value in person_info.items():
print(title + ":" + info_value)
else:
print('联系人不存在')
else:
print("通讯录为空")
需要注意的是, loads()函数只能将具有单引号的字符串转换为字典。
(4)在TelephoneBook类中定义main ()方法。main()方法实现访问一次通讯录的完整流程,该方法只需要在相应的分支语句中调用相应的方法即可,并将所有的代码放到循环语句中,以保证程序能一直运行,直至用户主动退出通讯录,具体代码如下。
def main(self):
while True:
self.show_menu()
action_str = input("请选择操作功能:") # 判断用户输入的功能指令
if action_str.isdigit() is True:
if int(action_str) == 1:
self.add_info()
elif int(action_str) == 2:
self.show_info()
elif int(action_str) == 0:
sys.exit()
else:
print('请输入正确的指令')
(5)创建一个TelephoneBook类对象,调用main()方法,具体代码如下。
if __name__ == '__main__':
tb = TelephoneBook()
tb.main()
代码测试
新建联系人的运行结果如下所示:
********************
欢迎使用[通讯录] V1.0
1. 新建联系人
2. 查询联系人
0. 退出系统
********************
请选择操作功能:1
请输入姓名:小明
成功添加小明为联系人
程序运行后在当前目录下可以看到生成的“通讯录.txt”文件,打开该文件后的内容如图1所示。
- 通讯录内容
查询联系人的运行结果如下所示:
********************
欢迎使用[通讯录] V1.0
1. 新建联系人
2. 查询联系人
0. 退出系统
********************
请选择操作功能:2
请输入要查询的姓名:小朋
联系人不存在
********************
欢迎使用[通讯录] V1.0
1. 新建联系人
2. 查询联系人
0. 退出系统
********************
请选择操作功能:2
请输入要查询的姓名:小明
姓名:小明
手机号:123