多继承的秘密
继承有两种方式:
1、classname.function(self)
2、super().function()
这两种方法有何区别和弊端呢?代码如下
使用 classname.function(self) 方法来实现继承
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): # 多重继承,使用 classname.function(self) 方式 num_sub_calls = 0 def call_me(self): LeftSubclass.call_me(self) RightSubclass.call_me(self) print("Calling method on Subclass") self.num_sub_calls += 1 s = Subclass() s.call_me() print(s.num_base_calls, s.num_right_calls, s.num_left_calls, s.num_sub_calls) 结果: Calling method on base class Calling method on left subclass Calling method on base class Calling method on right subclass Calling method on Subclass 2 1 1 1 # 这里不难看出,基类的call_me被调用了两次,这在某些业务里面会存在BUG
使用 super().function() 实现继承
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 s = Subclass() s.call_me() print(s.num_base_calls, s.num_right_calls, s.num_left_calls, s.num_sub_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方法只被调用了一次
总结:
classname.function(self):Subclass的call_me方法调用了LeftSubclass.call_me(self)和 RightSubclass.call_me(self)方法,他们同时去调基类的call_me方法,所以导致基类的方法被调用了两次。
super().function():Subclass的call_me方法调用了super().call_me(),其实他是先去调 LeftSubclass这个类里面的call_me方法,但这时super引用了 RightSubclass.call_me,并没有直接去访问基类的call_me,而是把权限给了RightSubclass,由RightSubclass去调基类的方法,通过super调用保证了在类的层次结构中,每个方法被调用一次。