Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python super()和直接调用超类的区别_Python_Oop_Python 2.7_Python 3.x_Superclass - Fatal编程技术网

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

Python super()和直接调用超类的区别,python,oop,python-2.7,python-3.x,superclass,Python,Oop,Python 2.7,Python 3.x,Superclass,在Python 2.7和3中,我使用以下方法调用超类的函数: class C(B): def __init__(self): B.__init__(self) 我发现也可以用super(B,self)替换B.。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 这样做有什么优点或缺点吗?至少对

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

class C(B):
    def __init__(self):
        B.__init__(self)
我发现也可以用
super(B,self)替换
B.。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


这样做有什么优点或缺点吗?至少对我来说,直接从
B
调用它更有意义,但可能有一个很好的理由,即
super()
只能在使用元类时使用(我通常避免使用元类)。

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

然而,多重继承带来了真正的好处。使用
super
时,单个调用不仅会自动调用所有基类型的方法(按照正确的继承顺序),而且还会确保每个方法只调用一次

这本质上允许类型具有一个属性,例如,您有一个单一的基类型
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>
这是输出:

>>> D2()
A2
B2
A2
C2
D2
<__main__.D2 object at 0x0000000003734E48>
>>D2()
A2
地下二层
A2
C2
D2

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

对于单继承,
super()
只是引用基类型的一种更为奇特的方式。这样,您可以使代码更易于维护,例如,如果您想更改基类型的名称。当您在任何地方都使用
super
时,只需在
class
行中对其进行更改

然而,多重继承带来了真正的好处。使用
super
时,单个调用不仅会自动调用所有基类型的方法(按照正确的继承顺序),而且还会确保每个方法只调用一次

这本质上允许类型具有一个属性,例如,您有一个单一的基类型
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>
这是输出:

>>> D2()
A2
B2
A2
C2
D2
<__main__.D2 object at 0x0000000003734E48>
>>D2()
A2
地下二层
A2
C2
D2

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

基本类型:?。基类、子类等:)似乎更多natural@MikeWilliamson你的理解部分正确。当调用
super()
时,确定顺序的逻辑实际上不会被计算。顺序的基础是Python中的方法解析顺序(MRO),它基本上是类型层次结构的一致线性化。您可以通过查看
D来查看
D的MRO。基本上是
D、C、B、A、object
。不幸的是,正确计算MRO有点复杂;它使用。但是简化了,你的“看”模型是有效的。@MikeWilliamson
super()
所做的不是计算下一步,而是简单地告诉Python在MRO中继续。这就是为什么所有属于层次结构的类都应该使用
super()
,这也是
a
调用
super()
的原因。如果您要添加另一个类型
类X(对象)
,并使
D
也继承自该类型,那么您将看到,如果没有
A
super()
,将不会调用
X
。由于在MRO中,
X
位于
A
之后,因此需要使用
super()
命令Python在MRO中继续。@MikeWilliamson我不知道你的意思。。MRO是使用该算法计算的(这可能会变得非常复杂;请查看Wikipedia上的示例)。计算MRO后,
super()
调用将按该顺序调用类型。当然,由于
super()
是函数调用,因此之后它会以相反的顺序返回;但那只是调用堆栈。@Piyuskansal在类
C
中,
super()
做的事情与
super(C,self)
做的事情相同。Python3引入了这个shorcut,您不需要为默认情况指定参数。在大多数情况下(大约99%),您只想使用
super()
。通过向它传递不同的类型,例如
super(ParentType,self)
,您将跳过MRO中的类型,因此这可能不是您想要做的。基本类型:?。基类、子类等:)似乎更多natural@MikeWilliamson你的理解部分正确。