第20天 继承应用 派生 super应用 继承属性查找 mixins机制 组合

继承应用模板

学生选课系统案例模板
class Student:
    school = "虹桥校区"

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def choose(self):
        print("%s 选课成功" % self.name)


stu1 = Student("lili", 18, "female")
stu2 = Student("nana", 16, "female")
stu3 = Student("dada", 19, "male")


class Teacher:
    school = "虹桥校区"

    def __init__(self, name, age, gender, level):
        self.name = name
        self.age = age
        self.gender = gender
        self.level = level

    def score(self):
        print("%s 正在为学生打分" % self.name)


tea1 = Teacher("egon", 18, "male", 10)
tea2 = Teacher("lxx", 26, "male", 3)

派生
在子类派生的新方法中重用父类的功能
继承了父类的功能后,子类定义了新的功能这种形式称为派生

方式一:指名道姓地引用某一类的函数,与继承无关
class Abb:
    school = "虹桥校区"

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(Abb):
    def choose(self):
        print("%s 选课成功" % self.name)


stu1 = Student("lili", 18, "female")
stu2 = Student("nana", 16, "female")
stu3 = Student("dada", 19, "male")


# 继承了父类的功能后,子类定义了新的功能这种形式称为派生
class Teacher(Abb):
    def __init__(self, name, age, gender, level):  # 形参
        Abb.__init__(self, name, age, gender)  # 实参
        self.level = level

    def score(self):
        print("%s 正在为学生打分" % self.name)


tea1 = Teacher("egon", 18, "female", 10)
tea2 = Teacher("biu", 19, "male", 20)
print(tea1.__dict__)

super应用

方式二:super()返回一个特殊的对象,该对象会参考发起属性查找的那一个类的mro列表.去当前类的父类中找属性
class Abb:
    school = "虹桥校区"

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(Abb):
    def choose(self):
        print("%s 选课成功" % self.name)


stu1 = Student("lili", 18, "female")
stu2 = Student("nana", 16, "female")
stu3 = Student("dada", 19, "male")


# 继承了父类的功能后,子类定义了新的功能这种形式称为派生
class Teacher(Abb):
    def __init__(self, name, age, gender, level):  # 形参
        # Abb.__init__(self, name, age, gender)  # 实参
        super().__init__(name, age, gender)  # super()返回一个特殊的对象,该对象会参考自己当前所在的那一个类的mro列表.去当前类的父类中找属性
        # super(Teacher,self).__init__(name, age, gender) python2中的用法
        self.level = level

    def score(self):
        print("%s 正在为学生打分" % self.name)


tea1 = Teacher("egon", 18, "female", 10)
tea2 = Teacher("biu", 19, "male", 20)
print(tea1.__dict__)

继承属性查找
单继承的查找顺序,经典类,新式类的查找顺序式一样的
mro()会显示类的继承顺序,mor列表会按照从左到右开始查找父类,直到找到第一个匹配这个属性的类为止

class C:
    x = 222


class B(C):
    pass


class A(B):
    pass


obj = A()
print(obj.x)
print(A.mro())  # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
print(B.mro())  # [<class '__main__.B'>, <class '__main__.C'>, <class 'object'>]

多继承背景下
如果新式类与经典类最后没有汇聚到一个点上,那么查找的顺序也是一样的,都是先从一个分支的深度查找
新式类,经典类多继承背景菱形继承查找顺序的差别

菱形继承/钻石继承:一个子类继承的多条分支,最终汇聚在一个非object的类上
经典类:深度优先
新式类:广度优先

经典类
第20天 继承应用 派生 super应用 继承属性查找 mixins机制 组合_第1张图片

新式类
第20天 继承应用 派生 super应用 继承属性查找 mixins机制 组合_第2张图片

新式类菱形继承查找代码呈现
class G(object):
    def test(self):
        print('from G')


class E(G):
    def test(self):
        print('from E')


class F(G):
    def test(self):
        print('from F')


class B(E):
    def test(self):
        print('from B')


class C(F):
    def test(self):
        print('from C')


class D(G):
    def test(self):
        print('from D')


class A(B, C, D):
    def test(self):
        print('from A')

    pass


obj = A()
obj.test()  # 查找顺序为:obj->A->B->E->C->F->D->G->object

案例:

class A:
    def test(self):
        print("from A")
        super().test()


class B:
    def test(self):
        print("from B")


class C(A, B):  # 查找顺序[C,A,B,object]
    pass


obj = C()
obj.test()
from A
from B
obj = A()  # 查找顺序[A,object]
obj.test()
from A ,object 里面没有test()所以会报错
注意:新式类里面的查找顺序,以属性发起者优先,找不到会从发起者的父类里面去找属性,
如果父类里面没有,会从第二个父类里面查找,应当遵循广度优先的原则

mixins机制(多继承的命名规范)
继承表达的是一个is-a的关系(尽可能的让一个子类归属一个父类,大量的重复代码都放在父类里面,把父类放在最右边,其他的父类主要用来添加功能)

代码呈现
class Vehicle:
    pass


class FlyableMixin:
    def fly(self):
        print("flying")


class CivilAircraft(FlyableMixin, Vehicle):
    pass


class Helicopter(FlyableMixin, Vehicle):
    pass


class Car(Vehicle):
    pass

组合

组合:组合表达的是一个has-a的关系,一个对象的属性是值是指向另外一个类的对象

class Abb:
    school = "虹桥校区"

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(Abb):
    def choose(self):
        print("%s 选课成功" % self.name)


# 继承了父类的功能后,子类定义了新的功能这种形式称为派生
class Teacher(Abb):
    def __init__(self, name, age, gender, level):  # 形参
        Abb.__init__(self, name, age, gender)  # 实参
        self.level = level

    def score(self):
        print("%s 正在为学生打分" % self.name)


class Course:
    def __init__(self, name, price, period):
        self.name = name
        self.price = price
        self.period = period

    def tell(self):
        print("课程信息:%s %s %s" % (self.name, self.price, self.period))


python = Course("python", 20000, "6mons")
linux = Course("linux", 20000, "5mons")

stu1 = Student("lili", 18, "female")
stu2 = Student("nana", 16, "female")
stu3 = Student("dada", 19, "male")

tea1 = Teacher("egon", 18, "female", 10)
tea2 = Teacher("biu", 19, "male", 20)

# stu1.course = python
# stu1.course.tell()

stu1.courses = []
stu1.courses.append(python)
stu1.courses.append(linux)

print(stu1.courses)
for course_obj in stu1.courses:
    course_obj.tell()

你可能感兴趣的:(python)