python 支持多继承:

任何实现多重继承的语言都要处理潜在的命名冲突,这种冲突由不相关的祖先类实现同名 方法引起。这种冲突称为“菱形问题”,如图 12-1 和示例 12-4 所示。

python3 class继承 _init__python


示例代码:

"""
python 中多继承:
"""
import pysnooper


class A:
    @pysnooper.snoop()
    def ping(self):
        print('A_ping:', self)


class B(A):
    @pysnooper.snoop()
    def pong(self):
        print('B_pong:', self)


class C(A):
    @pysnooper.snoop()
    def pong(self):
        print('C_PONG:', self)


class D(B, C):
    def ping(self):
        # 这里的super() 是调用B类
        super().ping()
        print('D_post-ping:', self)

    def pingpong(self):
        # 这里自身方法的调用,解析顺序和刚才一样
        self.ping()
        # 这里的super() 是调用B类
        super().ping()
        # 先查找自身,在查找B,在查找C,最后才会查找A
        self.pong()
        # 这里的super() 是调用B类
        super().pong()
        # 这里是调用C类方法
        C.pong(self)


if __name__ == "__main__":
    d = D()
    # 先查找自身,在查找B,在查找C,最后才会查找A
    d.pong()  # 依次放开,通过 pysnooper 可以看到执行顺序
    # d.ping()  # 依次放开,通过 pysnooper 可以看到执行顺序
    # d.pingpong()  # 依次放开,通过 pysnooper 可以看到执行顺序

1,放开 d.pong() 结果:

python3 class继承 _init__Python_02


2,放开 d.ping() , 注释 d.pong(),结果:

python3 class继承 _init__Python_03


3,放开 d.pingpong() , 注释 d.pong()d.ping() 结果:

python3 class继承 _init__执行顺序_04


当然也可以像下图的调用方式(超类中的方法都可以直接调用,此时要把实例作为显式参数传入。):

python3 class继承 _init__超类_05


Python 能区分 d.pong() 调用的是哪个方法,是因为 Python 会按照特定的顺序遍历继承图。 这个顺序叫方法解析顺序(Method Resolution Order,MRO)。类都有一个名为 __mro__ 的 属性,它的值是一个元组,按照方法解析顺序列出各个超类,从当前类一直向上,直到 object 类。D 类的 __mro__ 属性如下:

python3 class继承 _init__Python_06


若想把方法调用委托给超类,推荐的方式是使用内置的 super() 函数。在 Python 3 中,这 种方式变得更容易了,如示例 中 D 类的 pingpong 方法所示。然而,有时可能需要绕 过方法解析顺序,直接调用某个超类的方法——这样做有时更方便。如图:

python3 class继承 _init__python_07


注意,直接在类上调用实例方法时,必须显式传入 self 参数,因为这样访问的是未绑定方法(unbound method)。

python3 class继承 _init__python_08


然而,使用 super() 最安全,也不易过时。调用框架或不受自己控制的类层次结构中的方 法时,尤其适合使用 super()。使用 super() 调用方法时,会遵守方法解析顺序。

方法解析顺序不仅考虑继承图,还考虑子类声明中列出超类的顺序。也就是说,如果在 上面的代码中把 D 类声明为 class D(C, B):,那么 D 类的 __mro__ 属 性就会不一样:先搜索 C 类,再搜索 B 类。

查看几个类的 __mro__ 属性

python3 class继承 _init__python_09


python3 class继承 _init__python_10