最能感受到super函数的作用在于进行钻石继承的时候。
钻石继承:由一个基类衍生两个及以上的超类,然后在衍生,在类树的最底层生成一个子类,这样的类树结构就是一个类似 钻石外形,所以,最底层类继承称为钻石继承
首先:
这是直接通过超类调用方法给子类使用
class baseClass:
num_base_calls = 0
def call_me(self):
print("Calling method on Base Class")
self.num_base_calls += 1
class leftSubClass(baseClass):
num_left_calls = 0
def call_me(self):
baseClass.call_me(self)
print("Calling method on left SubClass")
self.num_left_calls += 1
class rightSubClass(baseClass):
num_right_calls = 0
def call_me(self):
baseClass.call_me(self)
print("Calling method on right SubClass")
self.num_right_calls += 1
class SubClass(leftSubClass, rightSubClass):
num_sub_calls = 0
def call_me(self):
rightSubClass.call_me(self)
leftSubClass.call_me(self)
print("Calling method on SubClass")
self.num_sub_calls += 1
s = SubClass()
print(s.call_me())
print(s.num_sub_calls, s.num_left_calls, s.num_right_calls, s.num_base_calls)
结果是:
Calling method on Base Class
Calling method on right SubClass
Calling method on Base Class
Calling method on left SubClass
Calling method on SubClass
1 1 1 2
这是通过super()函数实现继承
class baseClass:
num_base_calls = 0
def call_me(self):
print("Calling method on Base Class")
self.num_base_calls += 1
class leftSubClass(baseClass):
num_left_calls = 0
def call_me(self):
super().call_me()
print("Calling method on left SubClass")
self.num_left_calls += 1
class rightSubClass(baseClass):
num_right_calls = 0
def call_me(self):
super().call_me()
print("Calling method on right SubClass")
self.num_right_calls += 1
class SubClass(leftSubClass, rightSubClass):
num_sub_calls = 0
def call_me(self):
super().call_me()
print("Calling method on SubClass")
self.num_sub_calls += 1
# 使用super()实例化一个超类对象可以实现,每个层次只是进行且只进行一次调用
# 就拿这个例子来说
s = SubClass()
print(s.call_me())
print(s.num_sub_calls, s.num_left_calls, s.num_right_calls, s.num_base_calls)
结果是:
Calling method on Base Class
Calling method on right SubClass
Calling method on left SubClass
Calling method on SubClass
1 1 1 1
通过以上两个测试,第一个我们用超类直接调用他的方法在子类中实现了继承,但是我们看到这样的话每个超类都会在调用自身的call_me方法的同时也会调用超类的超类中的call_me方法,这样,baseClass就被执行了两次。第二个我们使用了super()方法在call_me方法中继承了超类的方法,这样就像注释里说的,它会根据继承的层次一个一个类的调用,所以baseClass类并不会被调用两次。这就是super()函数的作用