有什么区别:
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
and:
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
我看到super在只有单一继承的类中被大量使用。我可以理解为什么在多重继承中使用它,但不清楚在这种情况下使用它的优势是什么。
考虑下面的代码:
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)一样简单。这就是为什么超级可能是更好的选择。
有很多很棒的答案,但对于视觉学习者来说:
首先让我们来探讨与参数超,然后没有。
假设有一个从jack类创建的实例jack,它具有如图中绿色所示的继承链。调用:
超级(杰克,杰克).method(…)
将使用jack的MRO(方法解析顺序)(其继承树按一定顺序),并从jack开始搜索。为什么可以提供父类?如果我们从实例jack开始搜索,它会找到实例方法,重点是找到它的父方法。
如果不向super提供参数,就像传入的第一个参数是self类,传入的第二个参数是self。这些在Python3中是自动计算的。
然而,假设我们不想使用Jack的方法,而不是传入Jack,我们可以传入Jen,开始向上搜索Jen的方法。
它一次搜索一个层(宽度而不是深度),例如,如果Adam和Sue都有所需的方法,来自Sue的方法将首先被找到。
如果Cain和Sue都有所需的方法,则会首先调用Cain的方法。
这在代码中对应于:
Class Jen(Cain, Sue):
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中的哪个位置开始搜索。