Python类中如何调用父类?
- 直接写父类的名字
- 使用不带参数的super()方法
- 使用带参数的super(父类)方法
第1种方法比较简单,直接在调用的时候指定父类名称即可。但是这种直接使用的方式会有一个副作用,当存在多重继承的时候,父类的初始化方法会被多次调用。解决方法就是使用不带参数的super方法,该方法会使用一个D3算法,该算法会确保所有类的初始化方法仅仅调用一次。看例子:
class Parent(object):
def __init__(self, name, *args, **kwargs):
print("init Parent begin")
self.name = name
print("init Parent End")
class Son1(Parent):
def __init__(self, name, gender, *args, **kwargs):
print("init Son1 begin")
self.gender = gender
super().__init__(name, *args, **kwargs)
print("init Son1 End")
class Son2(Parent):
def __init__(self, name, age, *args, **kwargs):
print("init Son2 begin")
self.age = age
super().__init__(name, *args, **kwargs)
print("init Son2 End")
class Grandson(Son1, Son2):
def __init__(self, name, gender, age):
print("init Grandson begin")
super().__init__(name, gender, age)
print("init Grandson End")
print(Grandson.mro())
grandson = Grandson("zhangsan", "M", 23)
print("name = %s"%grandson .name)
print("gender = %s"%grandson .gender)
print("age = %s"%grandson .name)
输出结果如下:
[<class ‘main.Grandson’>, <class ‘main.Son1’>, <class ‘main.Son2’>, <class ‘main.Parent’>, <class ‘object’>]
上面的输出就是Grandson.mro()打印出来的对于多重继承调用super()时所采用的顺序,从下面的输出也可以跟上面进行对照,首先调用Grandson的初始化,然后调用Son1的初始化,再调用Son2的初始化,最后调用Parent的初始化。
init Grandson begin
init Son1 begin
init Son2 begin
init Parent begin
init Parent End
init Son2 End
init Son1 End
init Grandson End
如果把super都换成每个类的父类名,那么就可以得到下面的结果. 测试代码和结果如下,可以看到Parent被调用多次:
class Parent(object):
def __init__(self, name, *args, **kwargs):
print("init Parent begin")
self.name = name
print("init Parent End")
class Son1(Parent):
def __init__(self, name, gender, *args, **kwargs):
print("init Son1 begin")
self.gender = gender
super().__init__(name, *args, **kwargs)
print("init Son1 End")
class Son2(Parent):
def __init__(self, name, age, *args, **kwargs):
print("init Son2 begin")
self.age = age
super().__init__(name, *args, **kwargs)
print("init Son2 End")
class Grandson(Son1, Son2):
def __init__(self, name, gender, age):
print("init Grandson begin")
super().__init__(name, gender, age)
print("init Grandson End")
print(Grandson.mro())
grandson = Grandson("zhangsan", "M", 23)
print("name = %s"%grandson.name)
print("gender = %s"%grandson.gender)
print("age = %s"%grandson.age)
输出结果如下:
[<class ‘main.Grandson’>, <class ‘main.Son1’>, <class ‘main.Son2’>, <class ‘main.Parent’>, <class ‘object’>]
init Grandson begin
init Son1 begin
init Parent begin
init Parent End
init Son1 End
init Son2 begin
init Parent begin
init Parent End
init Son2 End
init Grandson End
name = zhangsan
gender = M
age = 23
如果继承的再多一些,Parent将被调用更多次,这是难以接受的,所以应该尽量使用super方法。
顺便说一句,supe()如果指定参数的话,会直接调用指定参数类的方法。将会打破MRO指定的默认顺序,跳转到对应类上去执行。