1. 单继承
使用super()函数在子类的init方法中对父类的init方法进行了调用,使得子类不仅可以使用父类的方法,还可以使用在父类的init方法中声明的属性。
1.1. 调用父类的方法和属性
without super()
class A:
def __init__(self):
self.x="A类(父类)中的属性"
def func_A(self):
print("A类(父类)中的方法")
print(self.x)
class B(A):
def __init__(self):
print("B类中的属性")
#super(B,self).__init__()
def func_B(self):
print("B类中原始的方法")
res = B()
res.func_A() #调用父类的方法
res.x #调用父类的属性
"""输出
B类中的属性
A类(父类)中的方法
AttributeError: 'B' object has no attribute 'x'
"""
可以看到没有用super时,调用属性会直接报错
- 重写父类的方法
class A:
def __init__(self):
self.x="A类(父类)中的属性"
def func_A(self):
print("A类(父类)中的方法")
class B(A):
def __init__(self):
print("B类中的属性")
#super(B,self).__init__()
def func_B(self):
print("B类中原始的方法")
def func_A(self):
print("重写A类(父类)中func_A的方法")
res = B()
res.func_A() #调用重写后的父类方法
res.x #调用父类的属性
"""输出
B类中的属性
重写A类(父类)中func_A的方法
AttributeError: 'B' object has no attribute 'x'
"""
可以看到不是用super,只能调用父类的方法,不能够调用属性
1.2. 调用方法和属性
with super()
class A:
def __init__(self):
self.x="A类(父类)中的属性"
def func_A(self):
print("A类(父类)中的方法")
print(self.x)
class B(A):
def __init__(self):
print("B类中的属性")
super(B,self).__init__() #继承父类的属性
def func_B(self):
print("B类中原始的方法")
res = B()
res.func_A()
res.x
"""输出
B类中的属性
A类(父类)中的方法
A类(父类)中的属性
'A类(父类)中的属性'
"""
可以看到在加入super()后,可以正常的调用父类的所有属性
- 方法重写后使用super()调用父类的方法
class A:
def __init__(self):
self.x="A类(父类)中的属性"
def func_A(self):
print("A类(父类)中的方法")
class B(A):
def __init__(self):
print("B类中的属性")
super(B,self).__init__() #继承父类的属性
def func_B(self):
print("B类中原始的方法")
def func_A(self):
print("重写A类(父类)中func_A的方法")
super(B,self).func_A() #继承父类的方法
res = B()
res.func_A() #调用重写后的父类方法
res.x #调用父类的属性
"""输出
B类中的属性
重写A类(父类)中func_A的方法
A类(父类)中的方法
'A类(父类)中的属性'
"""
2. 多继承
super与父类没有实质性的关联。在单继承时,super获取的类刚好是父类,但多继承时,super获取的是继承顺序中的下一个类。以下面的继承方式为例:
A
/ \
/ \
B C
\ /
\ /
D
class A(object):
def __init__(self):
print("enter A")
print("leave A")
class B(A):
def __init__(self):
print("enter B")
super(B, self).__init__()
print("leave B")
class C(A):
def __init__(self):
print("enter C")
super(C, self).__init__()
print("leave C")
class D(B, C):
def __init__(self):
print("enter D")
super(D, self).__init__()
print("leave D")
D() #多重继承
print(D.mro()) #查看继承结构
# 测试结果
"""
enter D
enter B
enter C
enter A
leave A
leave C
leave B
leave D
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
"""
3. 总结
- 使用super()进行父类方法和属性的调用是个好习惯
- 当使用super()时,建议误将父类的方法进行重写,否则该方法会被调用两次(父类和重写后的方法分别被调用)