class A(object):
def out(self):
print("A类方法")
class B(object):
def out(self):
print("B类方法")
class C(A, B):
pass
c = C()
# 打印C类的调用路径顺序(注意要类名.__mro__)
print(C.__mro__)
c.out()
运行结果:
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
A类方法
可以尝试一下把 C类
的继承顺序改成 B,A
class C(B, A):
pass
结果就是
(<class ‘main.C’>, <class ‘main.B’>, <class ‘object’>, <class ‘main.A’>)
B类方法
如果 C类
把 out()
方法重写那么将执行 C类的 out()
方法
class C(B, A):
def out(self):
print("C类方法")
结果如下:
(<class ‘main.C’>, <class ‘main.B’>, <class ‘object’>, <class ‘main.A’>)
C类方法
新式类可以直接通过
类名.__mro__
的方式获取类的MRO
,也可以通过类名.mro()
的形式,旧式类是没有 mro 属性和 mro() 方法的。
方法解析顺序 Method Resolution Order
,简称 MRO
。主要用于在多继承时判断方法,属性的调用路径。
mro()
输出的结果,从左到右的顺序查找的MRO
的顺序是根据 Python中C3算法 得来的大家感兴趣可以去研究一下,这里就不在赘述了。
在早期版本的 Python 中,所有类并没有一个共同的祖先 object
,如果定义一个类,但没有显式指定其祖先,那么就被解释为 旧式类,例如:
class oldA:
pass
class oldB:
pass
其中,oldA
和 oldB
都属于旧式类。
Python 2.x
版本中,为了向后兼容保留了旧式类。该版本中的 新式类必须 显式继承 object
或者其他新式类:
class NewA(object):
pass
class NewB(NewA):
pass
显然,以上两个类都属于 新式类。
而在 Python 3.x
版本中,不再保留旧式类的概念。因此,没有继承任何其他类的类都隐式地继承自 object
。
super()
函数是用于调用父类(超类)的一个方法。
super()
是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
"""
单继承使用父类名调用
"""
class Parent(object):
def eat(self):
print("\tparent --- 爱吃饭")
class Son1(Parent):
def eat(self):
print("son1 --- eat()")
Parent.eat(self)
print("\tson1 --- 爱吃蔬菜\n")
class Son2(Parent):
def eat(self):
print("son2 --- eat()")
Parent.eat(self)
print("\tson2 --- 爱吃水果\n")
def main():
s1 = Son1()
s2 = Son2()
s1.eat()
s2.eat()
if __name__ == '__main__':
main()
运行结果
son1 --- eat()
parent --- 爱吃饭
son1 --- 爱吃蔬菜
son2 --- eat()
parent --- 爱吃饭
son2 --- 爱吃水果
"""
单继承中super()的使用
"""
class Parent(object):
def eat(self):
print("\tparent --- 爱吃饭")
class Son1(Parent):
def eat(self):
print("son1 --- eat()")
super().eat()
print("\tson1 --- 爱吃蔬菜\n")
class Son2(Parent):
def eat(self):
print("son2 --- eat()")
super().eat()
print("\tson2 --- 爱吃水果\n")
def main():
s1 = Son1()
s2 = Son2()
s1.eat()
s2.eat()
if __name__ == '__main__':
main()
运行结果:
son1 --- eat()
parent --- 爱吃饭
son1 --- 爱吃蔬菜
son2 --- eat()
parent --- 爱吃饭
son2 --- 爱吃水果
可以发现在单继承使用 父类名
和 super()
调用父类方法结果都一样。
还是上面例子,就是加一个 GrandSon
类,让它继承 Son1, Son2
。让 eat()
具备其父类的特性。
"""
多继承中父类名的使用
"""
class Parent(object):
def eat(self):
print("\tparent --- 爱吃饭")
class Son1(Parent):
def eat(self):
print("son1 --- eat()")
Parent.eat(self)
print("\tson1 --- 爱吃蔬菜\n")
class Son2(Parent):
def eat(self):
print("son2 --- eat()")
Parent.eat(self)
print("\tson2 --- 爱吃水果\n")
class Grandson(Son1, Son2):
def eat(self):
print("grandson --- eat()")
# super().eat()
Son1.eat(self)
Son2.eat(self)
print("\tgrandson --- 爱吃零食")
def main():
# s1 = Son1()
# s2 = Son2()
# s1.eat()
# s2.eat()
g = Grandson()
g.eat()
if __name__ == '__main__':
main()
运行结果
grandson --- eat()
son1 --- eat()
parent --- 爱吃饭
son1 --- 爱吃蔬菜
son2 --- eat()
parent --- 爱吃饭
son2 --- 爱吃水果
grandson --- 爱吃零食
结果显示 Parent
的 eat()
方法调用了多次,存在重复调用。
"""
多继承中super()的使用
"""
class Parent(object):
def eat(self):
print("\tparent --- 爱吃饭")
class Son1(Parent):
def eat(self):
print("son1 --- eat()")
super().eat()
print("\tson1 --- 爱吃蔬菜\n")
class Son2(Parent):
def eat(self):
print("son2 --- eat()")
super().eat()
print("\tson2 --- 爱吃水果\n")
class Grandson(Son1, Son2):
def eat(self):
print("grandson --- eat()")
super().eat()
print("\tgrandson --- 爱吃零食")
def main():
g = Grandson()
g.eat()
if __name__ == '__main__':
main()
运行结果
grandson --- eat()
son1 --- eat()
son2 --- eat()
parent --- 爱吃饭
son2 --- 爱吃水果
son1 --- 爱吃蔬菜
grandson --- 爱吃零食
可以发现在多继承中使用 super()
没有重复调用。
假如在多继承中 Grandson
类的 eat()
方法只想复用 Parent, Son1
的 eat()
的方法,不需要 Son2
的。该如何实现呢?
父类名调用
"""
父类名的使用
"""
class Parent(object):
def eat(self):
print("\tparent --- 爱吃饭")
class Son1(Parent):
def eat(self):
print("son1 --- eat()")
Parent.eat(self)
print("\tson1 --- 爱吃蔬菜\n")
class Son2(Parent):
def eat(self):
print("son2 --- eat()")
Parent.eat(self)
print("\tson2 --- 爱吃水果\n")
class Grandson(Son1, Son2):
def eat(self):
print("grandson --- eat()")
Son1.eat(self)
# Son2.eat(self)
print("\tgrandson --- 爱吃零食")
def main():
print(Grandson.mro())
g = Grandson()
g.eat()
if __name__ == '__main__':
main()
结果如下
[<class '__main__.Grandson'>,
<class '__main__.Son1'>,
<class '__main__.Son2'>,
<class '__main__.Parent'>,
<class 'object'>
]
grandson --- eat()
son1 --- eat()
parent --- 爱吃饭
son1 --- 爱吃蔬菜
grandson --- 爱吃零食
[Finished in 0.1s]
super()调用
"""
super()的使用
"""
class Parent(object):
def eat(self):
print("\tparent --- 爱吃饭")
class Son1(Parent):
def eat(self):
print("son1 --- eat()")
super().eat()
print("\tson1 --- 爱吃蔬菜\n")
class Son2(Parent):
def eat(self):
print("son2 --- eat()")
super().eat()
print("\tson2 --- 爱吃水果\n")
class Grandson(Son1, Son2):
def eat(self):
print("grandson --- eat()")
super(Son1, self).eat()
# Son1.eat(self)
# Son2.eat(self)
print("\tgrandson --- 爱吃零食")
def main():
print(Grandson.mro())
g = Grandson()
g.eat()
if __name__ == '__main__':
main()
结果如下
[<class '__main__.Grandson'>,
<class '__main__.Son1'>,
<class '__main__.Son2'>,
<class '__main__.Parent'>,
<class 'object'>
]
grandson --- eat()
son2 --- eat()
parent --- 爱吃饭
son2 --- 爱吃水果
grandson --- 爱吃零食
[Finished in 0.1s]
然而却发现 super(Son1, self).eat()
调用的是 Son2
的 eat()
方法。
是因为 MRO
的原因,当调用 super(Son1,self).eat()
时 ,会拿 Son1
去 Grandson
的MRO方法解析顺序表 中寻找,找到然后 super()
调用则是列表中下一个,这里是 Son2
,然后 Son2.eat()
中使用了 super().eat()
,此时是拿其本身 Son2
在 Son2
的MRO方法解析顺序表 中寻找,然后 super().eat()
调用,则是列表的下一个 Parent.eat()
。
因此在 Grandson
中 super(Son1, self).eat()
调用的是 Son2.eat()
。
假如 super(Son2, self).eat()
调用的则是 Parent.eat()
。结果如下
[<class '__main__.Grandson'>,
<class '__main__.Son1'>,
<class '__main__.Son2'>,
<class '__main__.Parent'>,
<class 'object'>
]
grandson --- eat()
parent --- 爱吃饭
grandson --- 爱吃零食
因此只能使用 父类名 的形式调用 Son1.eat()
只继承 Son1
的特性。如果不清楚 super()
调用的谁,打印其
类名.mro(),对照 MRO方法解析顺序表,就一目了然。
Method Resolution Order
,简称 MRO
。主要用于在多继承时判断方法,属性的调用路径Python 2.x
版本中显式继承 object
或者其他新式类,Python3.x
中则是隐式继承object
super().method()
相对于 类名.method(self)
,在 单继承 上用法基本无差super()
方法 能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果新建文件夹X
大自然用数百亿年创造出我们现实世界,而程序员用几百年创造出一个完全不同的虚拟世界。我们用键盘敲出一砖一瓦,用大脑构建一切。人们把1000视为权威,我们反其道行之,捍卫1024的地位。我们不是键盘侠,我们只是平凡世界中不凡的缔造者 。