不会调用super()。

当从内建类型以及从其他类派生时,似乎内建类型的构造函数不会调用超类构造函数。 这会导致__init__方法不会被调用到MRO中内置的类型之后。

例:

class A:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print("A().__init__()")

class B(list, A):
    def __init__(self, *args, **kwargs):
        print("B().__init__() start")
        super().__init__(*args, **kwargs)
        print("B().__init__() end")

if __name__ == '__main__':
    b = B()

在这个例子中,A .__ init__永远不会被调用。 当B被定义为class B(A, list) - 切换继承顺序 - 它按预期工作(即调用A .__ init__)。

对继承秩序的这种非常微妙的依赖似乎是非pythonic,它是这样意思吗? 这也意味着你绝不能从复杂的类层次结构中的内建类型派生出来,因为当别人从你的类派生出来时(维护恐怖),你无法知道内置于MRO中的内容。 我错过了什么吗?

额外信息:Python版本3.1


super()的正确用法相当微妙,如果协作方法并不都具有相同的签名,则需要小心。 __init__()方法的通常模式如下所示:

class A(object):
    def __init__(self, param_a, **kwargs):
        self.param_a = param_a
        super(A, self).__init__(**kwargs)

class B(A):
    def __init__(self, param_b, **kwargs):
        self.param_b = param_b
        super(B, self).__init__(**kwargs)

class C(A):
    def __init__(self, param_c, **kwargs):
        self.param_c = param_c
        super(C, self).__init__(**kwargs)

class D(B, C):
    def __init__(self, param_d, **kwargs):
        self.param_d = param_d
        super(D, self).__init__(**kwargs)

d = D(param_a=1, param_b=2, param_c=3, param_d=4)

请注意,这要求所有方法协作,并且所有方法都需要一个稍微兼容的签名,以确保调用该方法时无关紧要。

内置类型的构造函数不具有允许参与此类协作的构造函数签名。 即使他们确实调用了super().__init__()除非所有的构造函数签名是统一的,否则这将毫无用处。 所以最后你是对的 - 他们不适合参与协作的构造函数调用。

只有在所有协作方法都具有相同签名(如__setattr__() )或者使用上述(或类似的)模式时才能使用super() 。 不过,使用super()并不是调用基类方法的唯一模式。 如果多重继承模式中没有“菱形”,则可以使用显式基类调用,例如B.__init__(self, param_a) 。 具有多个基类的类只需调用多个构造函数。 即使有钻石,只要你注意可以多次调用__init__()而没有伤害,你有时可以使用明确的调用。

如果你想使用super()作为构造object ,你确实不应该在多个侵害层次中使用内置类型的子类(除了object )。 进一步阅读:

  • Raymond Hettinger的Python超级()认为超级!
  • 詹姆斯奈特的Python的超级漂亮,但你不能使用它
  • 链接地址: http://www.djcxy.com/p/65017.html

    上一篇: doesn't call super().

    下一篇: ttk tkinter python3 multiple frames/windows