# 类的继承 ## 面向对象的继承 不用继承创建对象 ```python class Person: def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex class Cat: def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex class Dog: def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex ``` 使用继承的方式 ```python class Aniaml(object): def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex class Person(Aniaml): pass class Cat(Aniaml): pass class Dog(Aniaml): pass ``` 继承的优点也是显而易见的: 1. 增加了类的耦合性(耦合性不宜多,宜精)。 2. 减少了重复代码。 3. 使得代码更加规范化,合理化。 ## 继承的分类 上面的那个例子: - Aminal 叫做父类, 基类, 超类。 - Person Cat Dog: 子类,派生类。 继承:可以分**单继承,多继承**。 这里需要补充一下python中类的种类(继承需要): 在python2x版本中存在两种类.: - ⼀个叫**经典类**. 在python2.2之前. **不显式继承 `object`类**,是 Python2 的默认类定义方式。 - ⼀个叫**新式类**. 在python2.2之后出现了新式类, **显式继承 `object`类**(如 `class MyClass(object)`),是 Python2 引入的改进类模型。 python3x版本中只有一种类: python3中使⽤的都是**新式类**. 如果基类谁都不继承. 那这个类会默认继承 object ## 单继承 ### 类名,对象执行父类方法 ```python class Aniaml(object): type_name = '动物类' def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex def eat(self): print('吃',self) class Person(Aniaml): pass class Cat(Aniaml): pass class Dog(Aniaml): pass print(Person.type_name) Person.eat('东西') print(Person.type_name) p1 = Person('张三','男',18) print(p1.__dict__) print(p1.type_name) p1.type_name = '666' print(p1) p1.eat() ``` ### 执行顺序 ```python class Aniaml(object): type_name = '动物类' def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex def eat(self): print('吃',self) class Person(Aniaml): def eat(self): print('%s 用筷子吃饭'%self.name) class Cat(Aniaml): pass class Dog(Aniaml): pass p1 = Person('张三','男',18) p1.eat() ``` ### 同时执行类以及父类方法 方法一:如果想执行父类的func方法,这个方法并且子类中调用,那么就在子类的方法中写上:父类.func(对象,其他参数) ```python class Aniaml(object): type_name = '动物类' def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex def eat(self): print('吃东西') class Person(Aniaml): def __init__(self,name,sex,age,mind): Aniaml.__init__(self,name,sex,age) self.mind = mind def eat(self): Aniaml.eat(111) print('%s 吃饭'%self.name) class Cat(Aniaml): pass class Dog(Aniaml): pass p1 = Person('张三','男',18,'想吃东西') p1.eat() ``` 方法二:利用super,super().func(参数) ```python class Aniaml(object): type_name = '动物类' def __init__(self,name,sex,age): self.name = name self.age = age self.sex = sex def eat(self): print('吃东西') class Person(Aniaml): def __init__(self,name,sex,age,mind): # super(Person,self).__init__(name,sex,age) super().__init__(name,sex,age) self.mind = mind def eat(self): super().eat() print('%s 吃饭'%self.name) class Cat(Aniaml): pass class Dog(Aniaml): pass p1 = Person('张三','男',18,'想吃东西') p1.eat() ``` 单继承练习题 ```python class Base: def __init__(self,num): self.num = num def func1(self): print(self.num) class Foo(Base): pass obj = Foo(123) obj.func1() # 运⾏的是Base中的func1 ``` ```python class Base: def __init__(self,num): self.num = num def func1(self): print(self.num) class Foo(Base): def func1(self): print("Foo.func1",self.num) obj = Foo(123) obj.func1() # 运⾏的是Foo中的func1 ``` ```python class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) self.func2() def func2(self): print("Base.func2") class Foo(Base): def func2(self): print("Foo.func2") obj = Foo(123) obj.func1() # func1是Base中的 func2是⼦类中的 ``` ```python class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) self.func2() def func2(self): print(111, self.num) class Foo(Base): def func2(self): print(222, self.num) lst = [Base(1), Base(2), Foo(3)] for obj in lst: obj.func2() ``` ```python class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) self.func2() def func2(self): print(111, self.num) class Foo(Base): def func2(self): print(222, self.num) lst = [Base(1), Base(2), Foo(3)] for obj in lst: obj.func1() ``` ## 多继承 ```python class ShenXian: # 神仙 def fei(self): print("神仙都会⻜") class Monkey: # 猴 def chitao(self): print("猴⼦喜欢吃桃⼦") class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴 pass sxz = SunWukong() # 孙悟空 sxz.chitao() # 会吃桃⼦ sxz.fei() # 会⻜ ``` ### 经典类的多继承 ```python class A: pass class B(A): pass class C(A): pass class D(B, C): pass class E: pass class F(D, E): pass class G(F, D): pass class H: pass class Foo(H, G): pass ``` 画图 ![image-20210725220109579](03.%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF/image-20210725220109579.png) 在经典类中采⽤的是深度优先,遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个. 类的MRO(method resolution order): Foo-> H -> G -> F -> E -> D -> B -> A -> C. ### 新式类的多继承 #### mro序列 MRO是一个有序列表L,在类被创建时就计算出来。 通用计算公式为: mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )(其中Child继承自Base1, Base2) 如果继承至一个基类:class B(A) 这时B的mro序列为 mro( B ) = mro( B(A) ) = [B] + merge( mro(A) + [A] ) = [B] + merge( [A] + [A] ) = [B,A] 如果继承至多个基类:class B(A1, A2, A3 …) 这时B的mro序列 mro(B) = mro( B(A1, A2, A3 …) ) = [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] ) = ... 计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。 #### 表头和表尾 表头:列表的第一个元素 表尾:列表中表头以外的元素集合(可以为空) 示例:列表:[A, B, C] 表头是A,表尾是B和C #### 列表之间的+操作 [A] + [B] = [A, B] merge操作示例: 如计算merge( [E,O], [C,E,F,O], [C] ) 有三个列表 : ① ② ③ 1 merge不为空,取出第一个列表列表①的表头E,进行判断 各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表 2 取出列表②的表头C,进行判断 C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除 merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] ) 3 进行下一次新的merge操作 ...... --------------------- ![image-20210725220122519](03.%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF/image-20210725220122519.png) 计算mro(A)方式: mro(A) = mro( A(B,C) ) 原式= [A] + merge( mro(B),mro(C),[B,C] ) mro(B) = mro( B(D,E) ) = [B] + merge( mro(D), mro(E), [D,E] ) # 多继承 = [B] + merge( [D,O] , [E,O] , [D,E] ) # 单继承mro(D(O))=[D,O] = [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并删除D = [B,D,E] + merge([O] , [O]) = [B,D,E,O] mro(C) = mro( C(E,F) ) = [C] + merge( mro(E), mro(F), [E,F] ) = [C] + merge( [E,O] , [F,O] , [E,F] ) = [C,E] + merge( [O] , [F,O] , [F] ) # 跳过O,拿出并删除 = [C,E,F] + merge([O] , [O]) = [C,E,F,O] 原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C]) = [A,B] + merge( [D,E,O], [C,E,F,O], [C]) = [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳过E = [A,B,D,C] + merge([E,O], [E,F,O]) = [A,B,D,C,E] + merge([O], [F,O]) # 跳过O = [A,B,D,C,E,F] + merge([O], [O]) = [A,B,D,C,E,F,O] 那既然python提供了. 为什么我们还要如此⿇烦的计算MRO呢? 因为笔试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 正式项⽬开发的时候很少有⼈这么去写代码.