有什么区别:
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
and:
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
我看到super在只有单一继承的类中被大量使用。我可以理解为什么在多重继承中使用它,但不清楚在这种情况下使用它的优势是什么。
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
这很容易理解。
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
如果你使用super(Child,self)会发生什么?
当创建子实例时,它的MRO(方法解析顺序)是基于继承的(Child, SomeBaseClass, object)顺序。(假设SomeBaseClass除了默认对象之外没有其他父对象)
通过在self实例的MRO中传递Child、self、super搜索,并返回Child的next代理对象,在本例中是SomeBaseClass,该对象随后调用SomeBaseClass的__init__方法。换句话说,如果它是super(SomeBaseClass,self) super返回的代理对象将是object
对于多继承,MRO可以包含许多类,所以基本上super可以让您决定从MRO中的哪个位置开始搜索。
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
这很容易理解。
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
如果你使用super(Child,self)会发生什么?
当创建子实例时,它的MRO(方法解析顺序)是基于继承的(Child, SomeBaseClass, object)顺序。(假设SomeBaseClass除了默认对象之外没有其他父对象)
通过在self实例的MRO中传递Child、self、super搜索,并返回Child的next代理对象,在本例中是SomeBaseClass,该对象随后调用SomeBaseClass的__init__方法。换句话说,如果它是super(SomeBaseClass,self) super返回的代理对象将是object
对于多继承,MRO可以包含许多类,所以基本上super可以让您决定从MRO中的哪个位置开始搜索。
我曾经使用过super(),并且认识到我们可以改变调用顺序。
例如,我们有下一个层次结构:
A
/ \
B C
\ /
D
在这种情况下,D的MRO将是(仅适用于Python 3):
In [26]: D.__mro__
Out[26]: (__main__.D, __main__.B, __main__.C, __main__.A, object)
让我们创建一个类,其中super()在方法执行后调用。
In [23]: class A(object): # or with Python 3 can define class A:
...: def __init__(self):
...: print("I'm from A")
...:
...: class B(A):
...: def __init__(self):
...: print("I'm from B")
...: super().__init__()
...:
...: class C(A):
...: def __init__(self):
...: print("I'm from C")
...: super().__init__()
...:
...: class D(B, C):
...: def __init__(self):
...: print("I'm from D")
...: super().__init__()
...: d = D()
...:
I'm from D
I'm from B
I'm from C
I'm from A
A
/ ⇖
B ⇒ C
⇖ /
D
所以我们可以看到分辨率顺序和MRO是一样的。但是当我们在方法的开头调用super()时:
In [21]: class A(object): # or class A:
...: def __init__(self):
...: print("I'm from A")
...:
...: class B(A):
...: def __init__(self):
...: super().__init__() # or super(B, self).__init_()
...: print("I'm from B")
...:
...: class C(A):
...: def __init__(self):
...: super().__init__()
...: print("I'm from C")
...:
...: class D(B, C):
...: def __init__(self):
...: super().__init__()
...: print("I'm from D")
...: d = D()
...:
I'm from A
I'm from C
I'm from B
I'm from D
我们有一个不同的顺序,它颠倒了MRO元组的顺序。
A
/ ⇘
B ⇐ C
⇘ /
D
对于额外的阅读,我推荐下面的答案:
带有super的C3线性化示例(一个大层次结构)
新旧样式类之间的重要行为变化
关于新式课程的内幕
考虑下面的代码:
class X():
def __init__(self):
print("X")
class Y(X):
def __init__(self):
# X.__init__(self)
super(Y, self).__init__()
print("Y")
class P(X):
def __init__(self):
super(P, self).__init__()
print("P")
class Q(Y, P):
def __init__(self):
super(Q, self).__init__()
print("Q")
Q()
如果将Y的构造函数更改为X.__init__,你将得到:
X
Y
Q
但是使用super(Y, self).__init__(),你会得到:
X
P
Y
Q
P或Q甚至可能涉及到另一个文件,当你写X和Y时,你不知道,所以基本上,当你写类Y(X)时,你不知道super(Child, self)会引用什么,甚至Y的签名也像Y(X)一样简单。这就是为什么超级可能是更好的选择。