一、面向对象之继承
-
面向对象三大特性
面向对象三大特性:封装,继承,多态
-
继承
-
定义
如果一个类别A“继承自”另一个类别B就把这个A称为“B的子类”或“B的派生类”,而把B称为“A的父类”也可以称为“B是A的基类或超类”。
继承可以使的子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。
在子类继承父类的同时,可以重新定义某些属性,并重写某些方法(即覆盖父类的原有属性和方法)使其获得与父类不同的功能,也可为子类追加新的属性和方法
-
特点
- 增加了类的耦合性(耦合性不宜多,易精)
- 减少代码重复性
- 是的代码更加规范化,合理化
-
分类
继承可以分为单继承和多继承
在python2中x版本中存在两种类:
一个叫经典类,python2.2之前一直使用的使经典类,经典类在基类的根什么都不写
一个叫新式类,python2.2之后出现了新式类,新式类在基类的根是object类
python3中使用的都是新式类,如果基类谁都不继承,那这个类默认继承object
-
-
单继承
-
类名,对象执行父类方法
-
从类名执行父类的属性和方法
class Animal(object): live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print(f'self--->{self}') print('动物需要进食') class Person(Animal): pass print(Person.live) # 有生命的 print(Person.__dict__) # {'__module__': '__main__', '__doc__': None} Person.eat(12) # self--->12 # 动物需要进食
-
从对象执行父类的属性和方法
class Animal(object): live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print(f'self--->{self}') print('动物需要进食') class Person(Animal): pass p1 = Person('dsb',21,'laddy_boy') print(p1.__dict__) # {'name': 'dsb', 'age': 21, 'sex': 'laddy_boy'} print(p1.live) # 有生命的 # self---><__main__.Person object at 0x000001E8FC22F4E0> p1.eat() # 动物需要进食
注意:子类以及子类对象只能调用父类的属性以及方法,不能操作(增删改)
-
-
执行顺序
对象查找顺序先从对象空间找名字,再到子类找名字,然后去父类找名字
-
同时执行类以及父类方法
-
方法一
class Animal: live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print('动物都需要进食') class Person(Animal): def __init__(self,name,age,sex,hobby): Animal.__init__(self,name,age,sex)#调用Animal的__init__方法,当Person实例化时,将name,age,sex传递给Animal self.hobby = hobby def eat(self): print('人类需要进食') p1 = Person('铁憨憨',23,'男','锤人') print(p1.__dict__) # {'name': '铁憨憨', 'age': 23, 'sex': '男', 'hobby': '锤人'}
在对象的空间中调用父类的
__init__
方法,通过子类的实例化将父类__init__
所需的参数传进去。 -
方法二
class Animal: live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print('动物都需要进食') class Person(Animal): def __init__(self,name,age,sex,hobby): super().__init__(name,age,sex) self.hobby = hobby def eat(self): print('人类需要进食') super().eat() p1 = Person('铁憨憨',23,'男','锤人') p1.eat() # 人类需要进食 # 动物都需要进食
通过
super().__init__
的方式在对象空间中添加父类的属性
-
-
-
多继承
class God: def __init__(self,name): self.name = name def fly(self): print('会飞') def climb(self): print('神仙累了也需要爬树') class Monkey: def __init__(self,sex): self.sex = sex def climb(self): print('爬树') class MonkeySun(God,Money): pass sun = MonkeySun() sun.climb() # 神仙累了也需要爬树
-
经典类的多继承
虽然在python3中已经不存在经典类了. 但是经典类的MRO最好还是学⼀学. 这是⼀种树形结构遍历的⼀个最直接的案例,代码如下:
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
继承关系图如下:
在经典类中采⽤的是深度优先,遍历方案。⼀条路走到头,然后再回来,继续找下⼀个。
-
新式类的多继承
代码如下:
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 print(Foo.mro())
-
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操作 ...... ---------------------
继承关系图如下:
计算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]
-
-