Python札记35_多继承

浏览: 959

在上篇札记Python札记34中主要是讨论继承单继承方面的知识,本篇札记中主要是学习多继承的特点。

一个类是可以继承自多个父类的

class Person:   # 定义一个父类

def __init__(self, name): # 初始化函数
self.name = name #实例self的name属性

def age(self, n): # 创建age方法
return "The age of Peter is {}".format(n)

class Boy: # 定义Boy类
heigth = 180 # 定义类的属性heigth,下面直接调用
def color(self):
return "The boy is yellow"

class TallBoy(Person, Boy):
pass

if __name__ == "__main__":
boy = TallBoy("Peter")
print(boy.name)
print(boy.age(25))
print(boy.heigth)
print(boy.color())

结果:

Peter
The age of Peter is 25
180
The boy is yellow
  • Boy类有一个属性heigth=180,被实例化之后这个类属性也被继承到TallBoy中,因此boy.heigth能够获取到该属性值。
  • 继承多个类直接将类的名称写在括号里面
  • 父类的方法全部继承到子类中
  • 若子类重写了父类的方法,那么就使用子类的方法,父类的将被覆盖

继承的顺序问题
在Python2的新式类和Python3中,继承顺序都是“广度优先”,和算法MRO(Method Resolution Order)相关。

class K1:
def foo(self):
print("K1-foo")

class K2:

def foo(self):
print("K2-foo")

def bar(self):
print("K2-bar")

class J1(K1, K2):
pass

class J2(K1, K2):
def bar(self):
print("J2-bar")

class C(J1, J2):
pass

if __name__ == "__main__":
print(C.__mro__)
m = C()
m.foo()
m.bar()

结果为

(<class '__main__.C'>, <class '__main__.J1'>, <class '__main__.J2'>, <class '__main__.K1'>, <class '__main__.K2'>, <class 'object'>)
K1-foo
J2-bar
  • 其中mro是打印出类的继承顺序
  • 若执行foo()方法,首先找J1是否有此方法,若没有再看J2;都没有,再看J1继承的K1类,找到了foo()方法,即:C--->J1--->--->J2---K1
  • bar()方法同上的原理。
  • 关于MRO算法,记住一点:搜索是从左到右,可以参考
    stackoverflow
    Python进阶-Python的中MRO和Super

image.png

如果有继承关系如上图所示,应该怎么写出Python代码?笔者写法如下:

class D:
def foo(self):
print("foo in D")

def bar(self):
print("bar in D")

class E:
def bar(self):
print("bar in E")

class F:
def foo(self):
print("foo in F")

class B(D, E):
pass

class C(D, F):
def age(self, n):
print("His age is {}".format(n))

class A(B, C):
pass

a = A()
print(A.__mro__)
a.foo() # 先找B有没有foo,再找C;都没有,再找D,有foo
a.bar()
a.age(20)
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>)
foo in D
bar in D
His age is 20

对比代码:

class D:
def foo(self):
print("foo in D")

def bar(self):
print("bar in D")

class E:
def bar(self):
print("bar in E")

class F:
def foo(self):
print("foo in F")

class B(D, E):
pass

class C(F, D): # 代码中修改地方:将F和D类交换位置,再看结果的差异
def age(self, n):
print("His age is {}".format(n))

class A(B, C):
pass

a = A()
print(A.__mro__)
a.foo()
a.bar()
a.age(20)
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.E'>, <class 'object'>)
foo in F # 差别就是在这里:因为C类的继承改成了F,D。Python解释器在进行搜索的时候,先找类F中是否有foo方法
bar in D
His age is 20
推荐 0
本文由 皮大大 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册