继承

什么是继承

  继承就是新建类的一种方式,新建的类我们称为子类或者派生类;被继承的类我们称为父类或者基类,子类可以使用父类中的属性或者方法

为什么要用继承

  1、类解决了对象与对象之间的代码冗余问题

  2、继承解决的是类与类之间的代码冗余问题

如何使用继承

  1、新式类:继承了object类的子子孙孙类都是新式类

  2、经典类:没有继承了object类的子子孙孙类都是经典类

    注:经典类和新式类只有在python2中有区分,python3中只有新式类

  3、代码演示(学生选课为例)

 1 # 父类,公共类
 2 class People():
 3     school = 'SH'
 4 
 5     def __init__(self, name, age, gender):
 6         self.name = name
 7         self.age = age
 8         self.gender = gender
 9 
10 # 学生类
11 class Student(People):
12 
13     def __init__(self, name, age, gender, course=None):
14         if course is None:
15             course = []
16         People.__init__(self, name, age, gender)
17         self.courses = course
18 
19     def choose_course(self, course):
20         self.courses.append(course)
21         print('%s 选课成功 %s' % (self.name, self.courses))
22 
23 
24 stu = Student('tony', 19, 'male')
25 
26 # teacher类
27 class Teacher(People):
28 
29     def __init__(self, name, age, gender, level):
30         self.level = level
31         People.__init__(self, name, age, gender)
32 
33     def score(self, stu_obj, score):
34         stu_obj.score = score  # 给学生打分
35         print('%s给%s打了%s分' % (self.name, stu_obj.name, score))
36 
37 
38 tea = Teacher('tom', 19, 'male', 10)
39 print(tea.name)
40 print(tea.level)

单继承下属性查找

  1、代码练习

class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        #
        print('Foo.f2')
        self.f1()


class Bar(Foo):
    def f1(self):
        print('Bar.f1')


obj = Bar()  # {}
obj.f2()
# 结果
# Foo.f2
# Bar.f1

   2、练习

class Foo:
    def __f1(self):  # _Foo__f1()
        print('Foo.f1')

    def f2(self):
        #
        print('Foo.f2')
        self.__f1()  # _Foo__f1()


class Bar(Foo):
    def __f1(self):  # # _Bar__f1()
        print('Bar.f1')


obj = Bar()  # {}
obj.f2()

多继承下的属性查找

  1、新式类中是按照广度优先查找

   2、经典类:是按照深度优先查找

    3、练习

class A(object):
    def test(self):
        print('from A')


class B(A):
    # def test(self):
    #     print('from B')
    pass

class C(A):
    # def test(self):
    #     print('from C')
    pass


class D(B):
    # def test(self):
    #     print('from D')
    pass

class E(C):
    # def test(self):
    #     print('from E')
    pass


class F(D, E):
    # def test(self):
    #     print('from F')
    pass


f1 = F()
f1.test()

super()和mro()列表

  super()使用

class People():
    school = 'SH'

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

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

  mro()列表

    练习1

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


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


class C(A, B):
    pass


c = C()
c.test()

    练习2

class B:
    def test(self):
        print('B---->test')

    def aaa(self):
        print('B---->aaa')

class A:
    def test(self):
        print('A---->test')
        super().aaa()


class C(A, B):
    def aaa(self):
        print('C----->aaa')


c = A()
# c.test()  
print(A.mro())

  注:当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)

继承原理

  python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

>>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] 

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

    1.子类会先于父类被检查

    2.多个父类会根据它们在列表中的顺序被检查

    3.如果对下一个类存在两个合法的选择,选择第一个父类

父类限制子类的行为

class Animal():
    def speak(self):
        raise Exception('必须实现speak')
 
class People(Animal):
    def speak(self):
        pass

 

posted @ 2021-12-06 15:41  那就凑个整吧  阅读(58)  评论(0编辑  收藏  举报