一、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]:

  1. L[object] = [object]
  2. L[C(B1…BN)] = [C] + merge(L[B1],…,L[BN], [B1,…,BN])

这里的关键在于 merge,其输入是一组列表,按照如下方式输出一个列表:

  1. 检查第一个列表的头元素(如 L[B1] 的头),记作 H。
  2. 若 H 未出现在其它列表的尾部,则将其输出,并将其从所有列表中删除,然后回到步骤1;否则,取出下一个列表的头部记作 H,继续该步骤。
  3. 重复上述步骤,直至列表为空或者不能再找出可以输出的元素。如果是前一种情况,则算法结束;如果是后一种情况,说明无法构建继承关系,Python 会抛出异常TypeError。

这里只是简单叙述,看引用更加详细。

引用:

上面的说法还是比较抽象的,我们来看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()

继承关系图: 

python 类继承方法吗 python类的继承机制_后端

上面的代码执行结果:

python 类继承方法吗 python类的继承机制_后端_02

 执行到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]。

运行结果:

python 类继承方法吗 python类的继承机制_开发语言_03

 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__)

运行结果:

python 类继承方法吗 python类的继承机制_python 类继承方法吗_04

无法构建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__)

 运行结果:

python 类继承方法吗 python类的继承机制_后端_05

无法构建MRO。