2.5包,代码规范,案例
2.5.1 包
- 有2个或以上的模块有联系,他们都在同一文件夹下
- 文件夹中有
__init__.py
的文件 - 则这个文件夹就是一个包,包用于将模块文件组织起来
- 包能有效规避模块名冲突,能提高程序的结构性和可维护性
1.创建包
- 同一文件夹有2个或以上的模块有联系
- 在该文件夹里创建
__init__.py
文件
2. 导入包中模块
- 使用
import 包名.模块名
能够导入包中的模块 - 使用
from 包名.模块名 import...
能够导入模块中的符号 - 这样子导入是跳过了执行
__init__.py
文件 - 即使是在同一包中,也要输入包名,因为默认工作路径不在包下面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s6Cr9xCl-1610885407176)(\asset\Snipaste_2020-10-30_18-24-57.png)]
from Msg.SendMsg import send_test as s
from Msg.ReceMsg import receive_test as r
r()
s()
3.__init__
文件的作用
如果我们直接导入包,会发现没有作用,是因为我们之前没向__init__
文件写入任何代码,而这个文件就是控制包导入文件的。
- 包被导入时,会执行
__init__.py
文件的内容 __init__.py
的作用:控制包的导入行为,管理模块文件__init__.py
文件可以上面2节2种导入方法,可以直接导入模块,或者导入模块里的工具。并且也可以改名。- 导入工具的时候可以不写模块名,而是包名.工具
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c7Ij604W-1610885407182)(\asset\Snipaste_2020-10-30_19-28-50.png)]
拓展
from . import 模块名 = import 模块
# .代表当前文件夹
2.5.2 PEP8代码规范
-
缩进使用4个空格, 空格是首选的缩进方式. Python3 不允许混合使用制表符和空格来缩进.
-
每一行最大长度限制在79个字符以内.
-
顶层函数、类的定义, 前后使用两个空行隔开.
-
import 导入
-
导入建议在不同的行, 例如:
import os import sys # 不建议如下导包 import os, sys # 但是可以如下: from subprocess import Popen, PIPE
-
导包位于文件顶部, 在模块注释、文档字符串之后, 全局变量、常量之前. 导入按照以下顺序分组:
- 标准库导入
- 相关第三方导入
- 本地应用/库导入
- 在每一组导入之间加入空行
-
-
Python 中定义字符串使用双引号、单引号是相同的, 尽量保持使用同一方式定义字符串. 当一个字符串包含单引号或者双引号时, 在最外层使用不同的符号来避免使用反斜杠转义, 从而提高可读性.
-
表达式和语句中的空格:
- 避免在小括号、方括号、花括号后跟空格.
- 避免在逗号、分好、冒号之前添加空格.
- 冒号在切片中就像二元运算符, 两边要有相同数量的空格. 如果某个切片参数省略, 空格也省略.
- 避免为了和另外一个赋值语句对齐, 在赋值运算符附加多个空格.
- 避免在表达式尾部添加空格, 因为尾部空格通常看不见, 会产生混乱.
- 总是在二元运算符两边加一个空格, 赋值(=),增量赋值(+=,-=),比较(==,<,>,!=,<>,<=,>=,in,not,in,is,is not),布尔(and, or, not
-
避免将小的代码块和 if/for/while 放在同一行, 要避免代码行太长.
if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay()
-
永远不要使用字母 ‘l’(小写的L), ‘O’(大写的O), 或者 ‘I’(大写的I) 作为单字符变量名. 在有些字体里, 这些字符无法和数字0和1区分, 如果想用 ‘l’, 用 ‘L’ 代替.
-
类名一般使用首字母大写的约定.
-
函数名应该小写, 如果想提高可读性可以用下划线分隔.
-
如果函数的参数名和已有的关键词冲突, 在最后加单一下划线比缩写或随意拼写更好. 因此 class_ 比 clss 更好.(也许最好用同义词来避免这种冲突).
-
方法名和实例变量使用下划线分割的小写单词, 以提高可读性.
2.5.3 应用 学生名片信息管理系统 面向对象版
1.先回忆并且理清面向对象版的逻辑
1.1 存储学生信息的格式
"""
之前我们用学生空列表存储,每个学生用字典的形式嵌套
那么现在我们同样使用空列表存储,不同的是列表里存储的是对象。[学生对象1,学生对象2,····]
对象之前我们要先有类,才能进行实现
"""
class Student(object):
def __init__(self, _name, _age, _tel):
self.name = _name
self.age = _age
self.tel = _tel
student_list = []
stu1 = Student("Tom", 19, 12345677448)
# stu2·······
student_list.append(stu1)
1.2 实现对象列表的增删改查
'''
存储形式有了,接下来就是分析要如何进行增,删,改,查
'''
# 学生对象列表的增
add_name = input("请输入学生名字:")
add_age = input("请输入学生年龄:")
add_tel = input("请输入学生电话号澳门:")
# 同样进行一次判断 是否重名
for obj in student_list:
if obj.name == add_name:
print("已经有该学生信息,跳出")
break
else:
stu = Student(add_name, add_age, add_tel)
student_list.append(stu)
# 学生对象列表的查
for obj in student_list:
print("表头")
print(obj)
# 指定学生对象的查
check_name = input("请输入要查早的学生姓名:")
for obj in student_list:
if obj.name == check_name:
print("表头")
print(obj)
else:
print("查无此学生")
# 学生列表的改
edit_name = input("请输入要改的学生姓名:")
for obj in student_list:
if edit_name == obj.name:
pass
# 直接进行赋值更改
else:
print("查无此姓名")
# 学生列表的删
del_name = input("请输入要删除的学生姓名:")
for obj in student_list:
if del_name == obj.name:
student_list.remove(obj)
else:
print("查无此学生,删除失败")
1.3 实现对文件的操作
'''
增删改查进行完我们需要读取和存储这俩文件操作
对象是不能直接存储进文件的,我们需要把它改成字典再转成字符串才能写入
'''
# 首先进行文件的写入
user_list = []
for obj in student_list:
# 这里可以在学生类里多增添一个方法,返回字典
student_dict = obj.to_dict()
# 转化后给字典增添进新列表
user_list.append(student_dict)
# 之后将完整列表转为字符串
list_str = str(user_list)
with open("stu.txt", "w")as f:
f.write(list_str)
# 相反的 我们需要一个读取的操作
with open("stu.txt", "r")as f:
list_str = f.read()
# 将读取的字符串重新转为字典嵌套列表的格式
user_list = eval(list_str)
# 然后遍历列表重新转化为对象加进去原来的列表
for student_dict in user_list:
stu = Student(student_dict.name, student_dict.age, student_dict.tel)
student_list.append(stu)
2.把主逻辑学生管理系统也做成类
2.1 主面板逻辑
class ManageStuSys(object):
def __init__(self):
self.user_list = []
# 简陋表头作为一个静态方法 快速调用
@staticmethod
def table_top():
print("姓名\t\t年龄\t\t电话号码")
# 菜单不需要调用任何类属性和实例熟悉,故设为静态方法
@staticmethod
def menu():
print("=" * 10, "学生名片管理系统", "=" * 10)
print("1.添加学生信息")
print("2.查询所有学生信息")
print("3.查询指定学生信息")
print("4.修改指定学生信息")
print("5.删除指定学生信息")
print("6.保存档案")
print("7.读取档案")
print("8.退出系统")
print("=" * 40)
def main(self):
try:
self.load_init()
except Exception as read_e:
print("发生错误!,错误信息如下:文件不存在\n", read_e)
finally:
while True:
self.menu()
try:
user_select = input("请输入需要选择的功能:")
if user_select == '1':
print("添加学生信息")
self.add_stu_info()
elif user_select == '2':
print("查询所有学生信息")
self.check_all_stu()
elif user_select == '3':
print("查询指定学生信息")
self.check_stu()
elif user_select == '4':
print("编辑指定学生信息")
self.edit_stu()
elif user_select == '5':
print("删除指定学生信息")
self.del_stu()
elif user_select == '6':
save_file = input("请输入要保存的文件名:")
self.save_info(save_file)
elif user_select == '7':
load_file = input("请输入要读取的文件名:")
self.load_info(load_file)
elif user_select == '8':
print("退出学生名片管理系统")
break
else:
raise MenuInputError(user_select)
except Exception as e:
print("发生错误,错误信息为:", e)
2.2 学生信息的增
# 增添学生信息的面向对象版
def add_stu_info(self):
_name = input("请输入学生姓名:")
try:
_age = input("请输入学生年龄:")
if not 0 < int(_age) < 100:
raise AgeError(_age)
_tel = input("请输入学生电话号码:")
if len(_tel) != 11:
raise TelError(_tel)
except Exception as e:
print("输入有错误,错误信息为:", e)
else:
if self.is_valid_stu(_name):
print("系统已存在该学生信息,不需要重复添加")
else:
stu = Student(_name, _age, _tel)
self.user_list.append(stu)
print("添加成功")
2.3 学生信息的查
# 查询所有学生信息的面向对象版
def check_all_stu(self):
if not self.user_list:
print("系统内还没有学生信息,请读取档案或者手动增加学生信息")
else:
self.table_top()
for obj in self.user_list:
print(obj)
# 查询单独 或者 部分学生信息的面向对象版
def check_stu(self):
check_name = input("请输入想查询的学生姓名:")
for obj in self.user_list:
if obj.name == check_name:
print("查询到该学生信息如下")
self.table_top()
print(obj)
break
else:
print("学生档案里无此学生的相关信息,请重新确认")
2.5 学生信息的删除
# 删除指定的学生信息
def del_stu(self):
del_name = input("请输入想删除的学生姓名:")
for obj in self.user_list:
if obj.name == del_name:
print("查询到该学生信息如下")
self.table_top()
print(obj)
self.user_list.remove(obj)
print("该学生信息已删除")
break
else:
print("学生档案里无此学生的相关信息,请重新确认")
2.5 学生信息的删改
# 编辑指定的学生信息
def edit_stu(self):
edit_name = input("请输入要修改的学生名字:")
for obj in self.user_list:
if obj.name == edit_name:
print("查到此学生")
print("学生信息如下\n")
self.table_top()
print(f"{obj.name}\t\t{obj.age}\t\t{obj.tel}")
edit_name = input("请输入要更改的学生名字:")
for o_obj in self.user_list:
if edit_name == o_obj.name and edit_name != obj.name:
print("重新输入的名字和库里已有的学生信息重复了,请重新输入")
break
else:
edit_age = input("请输入要更改的学生年龄:")
edit_tel = input("请输入要更改的学生电话号码:")
try:
if not 0 < int(edit_age) < 100:
raise AgeError(edit_age)
if len(edit_tel) != 11:
raise TelError(edit_tel)
except Exception as e:
print("发生错误,错误信息为:", e)
else:
obj.name = edit_name
obj.age = edit_age
obj.tel = edit_tel
print("修改完成")
break
else:
print("学生档案里无此学生的相关信息,请重新确认")
2.6 文件操作
# 做保存文件的对象版
def save_info(self, save_file):
user_dict_list = []
for obj in self.user_list:
user_dict_list.append(obj.to_dict())
# 把对象列表,转换成字典列表,然后再写入文件中
if os.path.exists(save_file):
print("已有此文件,请问要覆盖吗?", end="")
user_sw = input("(yes or no):")
if user_sw == 'no':
return
else:
print("覆盖该文件")
with open(save_file, "w")as f:
f.write(str(user_dict_list))
print("写入成功")
# 做开程序的时候读取文件的对象版
def load_init(self):
with open("stu_info.config", "r")as f:
user_dict_list = eval(f.read())
for user_dict in user_dict_list:
stu = Student(user_dict['name'], user_dict['age'], user_dict['tel'])
self.user_list.append(stu)
print("读取完成")
# 做一个手动读取档案的对象版
def load_info(self, load_file):
try:
with open(load_file, "r")as f:
user_dict_list = eval(f.read())
for user_dict in user_dict_list:
stu = Student(user_dict['name'], user_dict['age'], user_dict['tel'])
self.user_list.append(stu)
print("读取完成")
except Exception as e:
print("发生错误,错误消息为:找不到文件", e)
3. 用try…except…实现自定义的报错
import os
from Stu.stu_module import Student
from Stu.input_error import AgeError, TelError, MenuInputError, ReadNoneError
class ManageStuSys(object):
save_op = 0
def __init__(self):
self.user_list = []
# 简陋表头作为一个静态方法 快速调用
@staticmethod
def table_top():
print("姓名\t\t年龄\t\t电话号码")
# 菜单不需要调用任何类属性和实例熟悉,故设为静态方法
@staticmethod
def menu():
print("=" * 10, "学生名片管理系统", "=" * 10)
print("1.添加学生信息")
print("2.查询所有学生信息")
print("3.查询指定学生信息")
print("4.修改指定学生信息")
print("5.删除指定学生信息")
print("6.保存档案")
print("7.读取档案")
print("8.退出系统")
print("=" * 40)
def main(self):
try:
self.load_init()
except Exception as read_e:
print("发生错误!,错误信息如下:文件不存在\n", read_e)
finally:
while True:
self.menu()
try:
user_select = input("请输入需要选择的功能:")
if user_select == '1':
print("添加学生信息")
self.add_stu_info()
elif user_select == '2':
print("查询所有学生信息")
self.check_all_stu()
elif user_select == '3':
print("查询指定学生信息")
self.check_stu()
elif user_select == '4':
print("编辑指定学生信息")
self.edit_stu()
elif user_select == '5':
print("删除指定学生信息")
self.del_stu()
elif user_select == '6':
save_file = input("请输入要保存的文件名:")
self.save_info(save_file)
self.save_op += 1
elif user_select == '7':
load_file = input("请输入要读取的文件名:")
self.load_info(load_file)
elif user_select == '8':
if self.check_save():
print("退出学生名片管理系统")
break
else:
raise MenuInputError(user_select)
except Exception as e:
print("发生错误,错误信息为:", e)
# 判断输入学生名字是否在表里是,实际上因为几次判断重复名字的需求都不是一致的,有的只是需求返回布尔,有的还需要同时返回遍历得到的数据
# 想太多了 只要我2个都返回同样的值,就可以了!运用了函数可以返回组包值的用法。多个数值返回的是一个元组。
def is_valid_stu(self, check_name):
for obj in self.user_list:
if obj.name == check_name:
return True, obj
else:
return False, ''
# 增添学生信息的面向对象版
def add_stu_info(self):
_name = input("请输入学生姓名:")
try:
_age = input("请输入学生年龄:")
if not 0 < int(_age) < 100:
raise AgeError(_age)
_tel = input("请输入学生电话号码:")
if len(_tel) != 11:
raise TelError(_tel)
except Exception as e:
print("输入有错误,错误信息为:", e)
else:
if self.is_valid_stu(_name)[0]:
print("系统已存在该学生信息,不需要重复添加")
else:
stu = Student(_name, _age, _tel)
self.user_list.append(stu)
print("添加成功")
# 查询所有学生信息的面向对象版
def check_all_stu(self):
if not self.user_list:
print("系统内还没有学生信息,请读取档案或者手动增加学生信息")
else:
self.table_top()
for obj in self.user_list:
print(obj)
# 查询单独 或者 部分学生信息的面向对象版
def check_stu(self):
check_name = input("请输入想查询的学生姓名:")
if self.is_valid_stu(check_name)[0]:
self.table_top()
print(self.is_valid_stu(check_name)[1])
else:
print("学生档案里无此学生的相关信息,请重新确认")
# 删除指定的学生信息
def del_stu(self):
del_name = input("请输入想删除的学生姓名:")
if self.is_valid_stu(del_name)[0]:
temp_obj = self.is_valid_stu(del_name)[1]
print("查询到该学生信息如下")
self.table_top()
print(temp_obj)
self.user_list.remove(temp_obj)
print("该学生信息已删除")
else:
print("学生档案里无此学生的相关信息,请重新确认")
# 编辑指定的学生信息
def edit_stu(self):
edit_name = input("请输入要修改的学生名字:")
if self.is_valid_stu(edit_name)[0]:
edit_name = input("请输入要更改的学生名字:")
for o_obj in self.user_list:
if edit_name == o_obj.name and edit_name != self.is_valid_stu(edit_name)[1].name:
print("重新输入的名字和库里已有的学生信息重复了,请重新输入")
break
else:
edit_age = input("请输入要更改的学生年龄:")
edit_tel = input("请输入要更改的学生电话号码:")
try:
if not 0 < int(edit_age) < 100:
raise AgeError(edit_age)
if len(edit_tel) != 11:
raise TelError(edit_tel)
except Exception as e:
print("发生错误,错误信息为:", e)
else:
temp_obj = self.is_valid_stu(edit_name)[1]
temp_obj.name = edit_name
temp_obj = edit_age
temp_obj.tel = edit_tel
print("修改完成")
else:
print("学生档案里无此学生的相关信息,请重新确认")
# 做保存文件的对象版
def save_info(self, save_file):
user_dict_list = []
for obj in self.user_list:
user_dict_list.append(obj.to_dict())
# 把对象列表,转换成字典列表,然后再写入文件中
if os.path.exists(save_file):
print("已有此文件,请问要覆盖吗?", end="")
user_sw = input("(yes or no):")
if user_sw == 'no':
return
else:
print("覆盖该文件")
with open(save_file, "w")as f:
f.write(str(user_dict_list))
print("写入成功")
self.save_op += 1
# 做开程序的时候读取文件的对象版
def load_init(self):
with open("stu_info.config", "r")as f:
user_dict_list = eval(f.read())
for user_dict in user_dict_list:
stu = Student(user_dict['name'], user_dict['age'], user_dict['tel'])
self.user_list.append(stu)
print("读取完成")
# 做一个手动读取档案的对象版
def load_info(self, load_file):
try:
with open(load_file, "r")as f:
if not f.read():
raise ReadNoneError
else:
# 注意 因为第一次判断已经读取了全部,导致光标在最后所以必须回移光标不然后面是铁定读成空
f.seek(0)
user_dict_list = eval(f.read())
for user_dict in user_dict_list:
stu = Student(user_dict['name'], user_dict['age'], user_dict['tel'])
self.user_list.append(stu)
print("读取完成")
except Exception as e:
print("发生错误,错误消息为:", e)
def check_save(self):
if self.save_op < 1:
user_sw = input("还没保存过,请问是否先保存?(yes or no): ")
if user_sw == 'yes':
return False
elif user_sw == 'no':
return True
else:
print("输入错误")
return True
if __name__ == '__main__':
mss = ManageStuSys()
mss.main()