super() 和直接调用超类的区别

问题描述 投票:0回答:2

在Python 2.7和3中,我使用以下方法来调用超类的函数:

class C(B):
    def __init__(self):
        B.__init__(self)

我发现也可以将

B.__init__(self)
替换为
super(B, self).__init__()
以及在 python3
super().__init__()
中。

无论哪种方式都有优点或缺点吗?至少对我来说,直接从

B
调用它更有意义,但也许有一个很好的理由,即
super()
只能在使用元类时使用(我通常避免使用)。

python oop python-2.7 python-3.x superclass
2个回答
76
投票

对于单一继承,

super()
只是一种引用基类型的更奇特的方式。这样,您可以使代码更易于维护,例如在您想要更改基本类型的名称时。当你在任何地方都使用
super
时,你只需要在
class
行中更改它即可。

真正的好处来自于多重继承。使用

super
时,单次调用不仅会自动调用所有基类型的方法(按照正确的继承顺序),而且还会确保每个方法仅被调用一次。

这本质上允许类型具有 diamond 属性,例如您有一个基本类型

A
,以及两种类型
B
C
,它们都派生自
A
。然后你就有了一个类型
D
,它继承自
B
C
(使其也隐式继承自
A
,两次)。如果您现在显式调用基类型的方法,您最终将调用 A 的方法两次。但是使用
super
,它只会调用一次:

class A (object):
    def __init__ (self):
        super().__init__()
        print('A')

class B (A):
    def __init__ (self):
        super().__init__()
        print('B')

class C (A):
    def __init__ (self):
        super().__init__()
        print('C')

class D (C, B):
    def __init__ (self):
        super().__init__()
        print('D')

当我们现在实例化

D
时,我们得到以下输出:

>>> D()
A
B
C
D
<__main__.D object at 0x000000000371DD30>

现在,让我们手动调用基本类型的方法来再次执行所有操作:

class A2 (object):
    def __init__ (self):
        print('A2')

class B2 (A2):
    def __init__ (self):
        A2.__init__(self)
        print('B2')

class C2 (A2):
    def __init__ (self):
        A2.__init__(self)
        print('C2')

class D2 (C2, B2):
    def __init__ (self):
        B2.__init__(self)
        C2.__init__(self)
        print('D2')

这是输出:

>>> D2()
A2
B2
A2
C2
D2
<__main__.D2 object at 0x0000000003734E48>

如您所见,

A2
出现了两次。这通常不是您想要的。当您手动调用使用
super
的基本类型之一的方法时,它会变得更加混乱。因此,您应该只使用
super()
来确保一切正常,而且您不必太担心。


0
投票

我对此的看法(我是 Python 的相对新手)是使用 super() 的整个想法是使用超类的方法。假设您有一个类 Vehicle,其属性之一为“self.owner”。您可以拥有汽车、卡车、公共汽车、飞机等子类,它们都有所有者,但因为所有权对于任何车辆(或者实际上,对于制造和出售的任何东西)都是相同的。使用每个子类来封装所有权是愚蠢的。

© www.soinside.com 2019 - 2024. All rights reserved.