一. 试验一下菱形问题下的属性查找顺序
"""
查找顺序: 经典类深度优先, 新式类广度优先
提示1: 只有python2中有经典类的概念, python3中默认继承或不继承object都是新式类.
提示2: python2中没有继承object的类及其子类都没有"类名.mro()"方法, 只有继承了才有. 而python3因为无论有没有显示继承都是默认继承object类, 所以由"类名.mro()"方法.
提示3: 深度优先, 广度优先都是基于当前分支最终继承的非object类当作参考点. 如果时深度优先则会在第一分支下就回去找. 如果时广度优先则会在最后分支中去找.
"""
"""
class G(object): # 在python2中,未继承object的类及其子类,都是经典类
def test(self):
print('from G')
pass
class E(G):
# def test(self):
# print('from E')
pass
class F(G):
# def test(self):
# print('from F')
pass
class B(E):
# def test(self):
# print('from B')
pass
class C(F):
# def test(self):
# print('from C')
pass
class D(G):
# def test(self):
# print('from D')
pass
class A(B, C, D):
# def test(self):
# print('from A')
pass
# 新式类
# print(A.mro()) # A -> B -> E -> C -> F -> D -> G -> object
# 经典类: 要放到python2中执行.
# print(A.mro()) # A -> B -> E -> G -> C -> F -> D
obj = A()
obj.test()
二. 在昨天基础之上优化
# 优化需求:
"""
1. 引入属性访问控制+property
2. 引入继承与派生的概念来减少代码冗余
注意:要满足什么"是"什么的关系,不满足"是"的关系不要去继承
"""
import os
import uuid
import pickle
class Base:
base_path = os.path.normpath(os.path.join(__file__, '..'))
def save(self):
dir_path = os.path.join(self.base_path, self.__class__.__name__.lower())
if not os.path.isdir(dir_path):
os.mkdir(dir_path)
path = os.path.join(dir_path, self.uuid)
with open(path, 'wb') as f:
pickle.dump(self, f)
@classmethod
def select(cls, uuid_name):
path = os.path.join(cls.base_path, cls.__name__.lower(), uuid_name)
if not os.path.isfile(path):
return
with open(path, 'rb') as f:
return pickle.load(f)
@classmethod
def get_uuid(cls):
dir_path = os.path.join(cls.base_path, cls.__name__.lower())
for uuid_name in os.listdir(dir_path):
if os.path.isdir(uuid_name):
continue
yield cls.select(uuid_name)
class School(Base):
__school_name = 'OldBoy'
def __init__(self, addr):
self.uuid = str(uuid.uuid1())
self.addr = addr
self.class_list = []
def related_class(self, class_obj):
self.class_list.append(class_obj)
def tell_class(self):
print(f'{self.__school_name}:{self.addr}'.center(50, '='))
for class_obj in self.class_list:
class_obj.tell_course()
class Class(Base):
def __init__(self, name):
self.uuid = str(uuid.uuid1())
self.name = name
self.course_obj = None
self.student_list = []
def related_course(self, course_obj):
self.course_obj = course_obj
def tell_course(self):
print(f'班级:{self.name}', end=' ')
print(self.course_obj)
def tell_student(self):
print(f'班级:{self.name}'.center(50, '='))
for student_obj in self.student_list:
print(student_obj)
class Course(Base):
def __init__(self, name, period, price):
self.uuid = str(uuid.uuid1())
self.name = name
self.period = period
self.price = price
def __str__(self):
return f'<课程:{self.name} 周期:{self.period}月 价格:{self.price}元>'
class People:
def __init__(self, name, age, sex='male'):
self.name = name
self.age = age
self.sex = sex
class Student(Base, People):
def __init__(self, name, age, sex='male'):
People.__init__(self, name, age, sex)
self.uuid = str(uuid.uuid1())
self.id_card = None
self.__score = None
def choose_class(self, class_obj):
id_card = max(range(len(class_obj.student_list) + 1))
self.id_card = id_card + 1
# class_obj.student_list.append(self)
class_obj.student_list.append(self)
@property
def score(self):
return self.__score
@score.setter
def score(self, score_value):
if not isinstance(score_value, int):
raise TypeError("对不起, 修改的成绩必须是整数!")
if not (0 <= score_value <= 100):
raise TypeError("对不起, 成绩输入范围:0~100")
self.__score = score_value
def __str__(self):
if self.__score:
score = f'成绩:{self.__score}分'
else:
score = ''
return f'学号:{self.id_card} 姓名:{self.name} 年龄:{self.age}岁 性别:{self.sex} {score}'
class Teacher(Base, People):
def __init__(self, name, age, salary, level, sex='male'):
People.__init__(self, name, age, sex)
self.uuid = str(uuid.uuid1())
self.salary = salary
self.level = level
@staticmethod
def modify_score(student_obj, score):
student_obj.score = score
# 实例化学校对象
school_obj1 = School('上海校区')
school_obj2 = School('北京校区')
school_obj3 = School('深圳校区')
# 实例化班级对象
class_obj1 = Class('脱产14期')
class_obj2 = Class('脱产15期')
class_obj3 = Class('脱产16期')
# 实例化课程对象
course_obj1 = Course('python', 6, 21800)
course_obj2 = Course('linux', 5, 19800)
course_obj3 = Course('go', 6, 20800)
# 实例化学生对象
student_obj1 = Student('张晨', 23)
student_obj2 = Student('刘旭', 28)
student_obj3 = Student('朱斌成', 24)
student_obj4 = Student('王律盛', 25)
student_obj5 = Student('陈诚', 23, 'female')
student_obj6 = Student('刘洋', 18)
# 实例化话老师对象
teacher_obj1 = Teacher('egon', 18, 99999, 9)
teacher_obj2 = Teacher('tank', 17, 100000, 8)
# 学校对象关联班级
school_obj1.related_class(class_obj1)
school_obj2.related_class(class_obj2)
school_obj3.related_class(class_obj3)
# 班级对象关联课程
class_obj1.related_course(course_obj1)
class_obj2.related_course(course_obj2)
class_obj3.related_course(course_obj3)
# 学生对象选择班级
student_obj1.choose_class(class_obj1)
student_obj2.choose_class(class_obj2)
student_obj3.choose_class(class_obj3)
student_obj4.choose_class(class_obj1)
student_obj5.choose_class(class_obj2)
student_obj6.choose_class(class_obj3)
# 老师对象修学生成绩
teacher_obj1.modify_score(student_obj1, 99)
teacher_obj2.modify_score(student_obj2, 88)
teacher_obj1.modify_score(student_obj3, 77)
teacher_obj2.modify_score(student_obj4, 66)
teacher_obj1.modify_score(student_obj5, 55)
teacher_obj2.modify_score(student_obj6, 44)
"""
# 学校对象查看班级
school_obj1.tell_class()
school_obj2.tell_class()
school_obj3.tell_class()
# 班级对象查看学生
class_obj1.tell_student()
class_obj2.tell_student()
class_obj3.tell_student()
"""
# 保存以上所有对象到文件
"""
school_obj1.save()
school_obj2.save()
school_obj3.save()
class_obj1.save()
class_obj2.save()
class_obj3.save()
course_obj1.save()
course_obj2.save()
course_obj3.save()
student_obj1.save()
student_obj2.save()
student_obj3.save()
student_obj4.save()
student_obj5.save()
student_obj6.save()
teacher_obj1.save()
teacher_obj2.save()
"""
# 更具学校类名拿到学校下的所有文件对象并打印班级信息
for school_obj in School.get_uuid():
school_obj.tell_class()
# 更具班级类名拿到班级下的所有文件对象并打印学生信息
for class_obj in Class.get_uuid():
class_obj.tell_student()