一、python的继承
python支持单继承和多继承,这种继承机制极大的提高了代码的复用性,使得子类可以继承父类和祖类的方法以及属性,这就是继承,同时,子类也可以重写父类和祖类的某个方法或者属性,从而使得子类可以获得与父类和祖类不一样的行为,这就是多态。
python作为一门支持oop的语言,其class(类)实现了封装,继承机制实现了继承与多态。
继承中非常重要的一点就是多态,当子类和父类以及祖类具有相同的属性或者方法的时候,python会调用哪个方法或者属性。
注意:python2与python3的多继承机制有所差别。在python2中多继承分为两种情况:如果是经典类(基类不是从object派生而来)的继承则为深度优先;如果是新式类(基类从object派生而来),然后继承的父类从同一个基类派生而来,那么广度优先;如果继承的父类从不同的基类派生而来,则其遍历顺序较为复杂,后面详细说明。在python3中取消了经典类,所以python3中只有新式类的继承。
1、单继承
单继承中,当我们通过子类.xxxx的调用一个实例的方法或者访问一个属性的时候,python首先会在子类中寻找该方法或者属性,如果没有寻找到就去父类中去寻找。如果在父类中没有找到该方法或者属性,就继续递归寻找(去父类的父类中去寻找,以此类推。这里需要注意:递归寻找的时候,如果父类还是单继承就按照单继承方法搜索,如果父类是多继承则按照多继承方法搜索。),直到找到一个名为xxxx的方法或属性,或者直到Object这个类为止。
2、多继承
多继承中,当我们通过子类.xxxx的调用一个实例的方法或者访问一个属性的时候,python就会按照一定的顺序去父类中寻找。该顺序按照一定的算法获得,在实例中可以通过xxx.__class__.__mro__获得这个搜索顺序列表。
计算MRO的算法:
类 C 的线性化(MRO)记为 L[C] = [C1, C2,…,CN]。其中 C1 称为 L[C] 的头,其余元素 [C2,…,CN] 称为尾。如果一个类 C 继承自基类 B1、B2、……、BN,那么我们可以根据以下两步计算出 L[C]:
L[object] = [object]
L[C(B1…BN)] = [C] + merge(L[B1],…,L[BN], [B1,…,BN])
这里的关键在于 merge,其输入是一组列表,按照如下方式输出一个列表:
- 检查第一个列表的头元素(如 L[B1] 的头),记作 H。
- 若 H 未出现在其它列表的尾部,则将其输出,并将其从所有列表中删除,然后回到步骤1;否则,取出下一个列表的头部记作 H,继续该步骤。
- 重复上述步骤,直至列表为空或者不能再找出可以输出的元素。如果是前一种情况,则算法结束;如果是后一种情况,说明无法构建继承关系,Python 会抛出异常TypeError。
这里只是简单叙述,看引用更加详细。
引用:https://blog.csdn.net/lengye7/article/details/121312262
上面的说法还是比较抽象的,我们来看3个例子。
1、完全的单继承例子
- class base:
- def hello(self):
- print("hello base!")
-
- class type1(base):
- def hello(self):
- print("hello type1!")
-
- class type2(base):
- def hello2(self):
- print("hello type2!")
-
- a = type1()
-
- a.hello()
-
- b = type2()
-
- b.hello()
-
- b.hello2()
继承关系图:
上面的代码执行结果:
执行到a.hello(),由于a是type1的实例,type1中具备hello方法,所以python直接调用type1中的hello方法,输出hello type1!。
执行到b.hello(),由于b是type2的实例,type2中不具备hello方法,所以python去父类base中去寻找,在父类base中找到hello方法并执行,输出hello base!。
执行到b.hello2(),由于b是type2的实例,type2中具备hello2方法,python直接执行hello2,输出hello type2!。
2、多继承的例子
1)、正确的例子
- class base:
- test = "test_base"
- def hello(self):
- print("hello base!",self.test)
-
- class type1(base):
- test = "test_type1"
- def hello(self):
- print("hello type1!",self.test)
-
- class type2(base):
- def hello2(self):
- print("hello type2!")
- class type3(type2,type1):
- def hello3(self):
- print("hello type3!")
-
- c = type3()
-
- c.hello()
-
-
- c.hello2()
-
-
- c.hello3()
-
- print(c.__class__.__mro__)
我们可以推测得到它的MRO:[type3,type2,type1,base,object]。
运行结果:
2)、错误的例子
形如,class test1(X,A,B)…..,q其中X是A或者B任意一个父类的基类,则会无法构建MRO,报错。
- class base:
- test = "test_base"
- def hello(self):
- print("hello base!",self.test)
-
- class type1(base):
- test = "test_type1"
- def hello(self):
- print("hello type1!",self.test)
-
- class type2(base):
- def hello2(self):
- print("hello type2!")
- class type3(base,type2,type1):
- def hello3(self):
- print("hello type3!")
-
- c = type3()
-
- c.hello()
-
- c.hello2()
-
- c.hello3()
-
-
- print(c.__class__.__mro__)
运行结果:
无法构建MRO。
形如:class test(A,B,C):……,其中A的MRO中存在[…,X,…,Y…],B的MRO中存在[…,Y,…,X,…],也会无法构建MRO,从而报错。
- class base:
- test = "test_base"
- def hello(self):
- print("hello base!",self.test)
-
- class type1(base):
- test = "test_type1"
- def hello(self):
- print("hello type1!",self.test)
-
- class type2(base):
- def hello2(self):
- print("hello type2!")
- class type3(type2,type1):
- def hello3(self):
- print("hello type3!")
-
- class type4(type1,type2):
- pass
-
- class type5(type4,type3):
- pass
- c = type5()
-
- c.hello()
-
- c.hello2()
-
- c.hello3()
-
-
- print(c.__class__.__mro__)
运行结果:
无法构建MRO。