python的多重继承:选择要调用的super()

Python's Multiple Inheritance: Picking which super() to call

在Python中,如何选择要调用哪个父级的方法?假设我想调用父级asdf2的__init__方法。似乎我必须在super()中指定asdf1。如果我想调用asdf3的__init__,那么我必须指定asdf2?!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> class ASDF(ASDF1, ASDF2, ASDF3):
    def __init__(self):
        super(ASDF1, self).__init__()


>>> ASDF()
ASDF2's __init__ happened
>>> class ASDF(ASDF1, ASDF2, ASDF3):
    def __init__(self):
        super(ASDF2, self).__init__()


>>> ASDF()
ASDF3'
s __init__ happened

我觉得很疯狂。我做错什么了?


这不是super()的目的。super基本上按照特定的顺序选择它的一个(或全部)父母。如果只想调用单个父级的方法,请执行此操作

1
2
3
class ASDF(ASDF1, ASDF2, ASDF3):
    def __init__(self):
        ASDF2.__init__(self)


super调用方法解析顺序中的下一个方法。在线性继承树中,这将是直接父类的方法。

在这里,你有三个父母,从ASDF1的角度来看,下一个__init__方法就是ASDF2方法。一般来说,安全的做法是将继承列表中的第一个类传递给super,除非您知道为什么要做其他事情。

所有这些的要点都是为了减轻您必须显式地选择要调用的__init__方法的负担。这里的问题是为什么您不想调用所有的超类__init__方法。

关于在python中使用super有相当多的文献,我建议您在谷歌上搜索这个主题,并阅读结果。


您正在将asdf1(父类之一)作为第一个参数传递给super()。不要那样做。相反,您应该将asdf作为第一个参数传递给super()。

Super()的python 2.7文档

要引用python2.7文档,典型的超类调用如下所示:

1
2
3
class C(B):
    def method(self, arg):
        super(C, self).method(arg)

注意,这里super的第一个参数是c,它是当前类。不要将b(父类)传递给super()。

在确定方法解析顺序(MRO)时,super跳过作为第一个参数传入的类,并开始查看该类的父类和同级。因此,当您将asdf1作为第一个参数传递给super()时,它跳过了asdf1,并使用asdf2开始搜索。这就是为什么asdf2的__init__被调用的原因。

在Python3中,您不再需要传递当前类。

1
2
3
4
5
class C(B):
    def method(self, arg):
        super().method(arg)    # This does the same thing as:
                               # super(C, self).method(arg)
                               # (Python 3 only)