欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多重继承-super使继承变得更清楚

程序员文章站 2022-05-29 23:06:28
...

多重继承的注意点,以及“下一个”的引用
详解super() 函数在多重继承中的作用

# 多重继承

# 多重继承的重复调用问题

class BaseClass:
    num_base_calls = 0
    def call_me(self):
        print("Calling method on BaseClass")
        self.num_base_calls += 1

class LeftSubClass(BaseClass):
    num_left_calls = 0
    def call_me(self):
        BaseClass.call_me(self)
        print("Calling methon on LeftC")
        self.num_left_calls += 1


class RightSubClass(BaseClass):
    num_right_calls = 0
    def call_me(self):
        BaseClass.call_me(self)
        print("Calling methon on RightC")
        self.num_right_calls += 1

class SubClass(LeftSubClass, RightSubClass):
    num_sub_calls = 0
    def call_me(self):
        LeftSubClass.call_me(self)
        RightSubClass.call_me(self)
        print("Calling method on SubC")
        self.num_sub_calls += 1

s = SubClass()
print(s.call_me())
# Calling method on BaseClass
# Calling methon on LeftC
# Calling method on BaseClass
# Calling methon on RightC
# Calling method on SubC
print(s.num_base_calls, s.num_left_calls, s.num_right_calls, s.num_sub_calls)
# 2 1 1 1

# 由上面可知,我们的base类的call_me方法被调用了两次,是绝对不允许的!


# 利用super函数实现调用“下一个方法”

class BaseClass:
    num_base_calls = 0
    def call_me(self):
        print("Calling method on BaseC")
        self.num_base_calls += 1

class LeftSubClass(BaseClass):
    num_left_calls = 0
    def call_me(self):
        super().call_me()
        print("Calling method on LeftC")
        self.num_left_calls += 1

class RightSubClass(BaseClass):
    num_right_calls = 0
    def call_me(self):
        super().call_me()
        print("Calling method on RightC")
        self.num_right_calls += 1

class SubClass(LeftSubClass, RightSubClass):
    num_sub_calls = 0
    def call_me(self):
        super().call_me()
        print("Calling method on SubC")
        self.num_sub_calls += 1

e = SubClass()
e.call_me()
# Calling method on BaseC
# Calling method on RightC
# Calling method on LeftC
# Calling method on SubC
print(e.num_base_calls, e.num_left_calls, e.num_right_calls, e.num_sub_calls)
# 1 1 1 1

# 注释:与直接调用超类中的方法不同的是,super()函数调用的对于
# 具有多个超类中,如果有多个相同的方法(比如这里,基类和同等级的类中都有
# 相同的方法,那么,super函数调用的是同等级类中的方法,也就是俗称的“下一个”方法

# 从上面和这里可以看出,super函数实例化的一个对象是“下一个”类的实例化

进一步解释一下就是对于一个钻石继承的例子来说
![如图就是一个钻石继承的基本图形多重继承-super使继承变得更清楚
也就是说,super()函数会调用其所在的类的的几个基类的相同的方法
假如super()函数所在的类是SubClass类,它从左到右继承了两个基类(LeftSubClass和RightSUbclass),且两个基类中
都有相同(call_me)的方法,那么,他会从左到右依次调用每一个基类中的方法,再从BaseClass调用call_me方法。
假如每一个call_me方法中都有参数的话,我们都是用关键字参数就可以了,然后对于super函数对于参数的引用直接使用**kwargs就可以了,它会自动将这个类用不上的参数关键字参数包装成字典传递给下一个类中的方法。