class A: def __init__(self): print("world") class B(A): def __init__(self): print("hello") B() # output: hello
在所有其他语言中,我使用的超级构造函数都是隐式调用的。在 Python 中如何调用它?我期望 super(self),但这不工作。
super(self)
super()返回类父对象在新式课堂上:
super()
class A(object): def __init__(self): print("world") class B(A): def __init__(self): print("hello") super(B, self).__init__() B()
使用Python 2。X个老式的类,它是这样的:
class A: def __init__(self): print "world" class B(A): def __init__(self): print "hello" A.__init__(self)
一种方法是调用A的构造函数并传递self作为参数,如下所示:
self
class B(A): def __init__(self): A.__init__(self) print "hello"
这种风格的优点是非常清晰。它调用A的初始化式。缺点是它不能很好地处理菱形继承,因为您可能会两次调用共享基类的初始化式。
另一种方法是使用super(),就像其他人展示的那样。对于单继承,它所做的基本上与让你调用父类的初始化式相同。
但是,super()在底层要复杂得多,在多重继承的情况下有时可能与直觉相反。好的方面是,super()可以用来处理菱形继承。如果你想知道super()做了什么,我找到的关于super()如何工作的最好解释是在这里(尽管我并不一定赞同那篇文章的观点)。
与其他答案一致,在Python-3中有多种调用超类方法的方法(包括构造函数)。X流程已简化:
python - 3. x
class A(object): def __init__(self): print("world") class B(A): def __init__(self): print("hello") super().__init__()
python - 2. x
在python中2。x,你必须调用稍微啰嗦一点的版本super(<containing classname>, self),它相当于super()as for 的文档。
super(<containing classname>, self)
class A(object): def __init__(self): print "world" class B(A): def __init__(self): print "hello" super(B, self).__init__()
我用下面的公式扩展了之前的答案:
class A(object): def __init__(self): print "world" class B(A): def __init__(self): print "hello" super(self.__class__, self).__init__() B()
这样你就不必在超级调用中重复类名。如果您正在编写大量的类,并且想要使初始化方法中的代码独立于类名,那么它可以派上用场。
简短的回答
super(DerivedClass, self).__init__()
长回答
super()做什么?
它接受指定的类名,找到它的基类(Python允许多重继承),并从左到右在每个基类中查找方法(在本例中为__init__)。一旦找到可用的方法,它将调用它并结束搜索。
__init__
如何调用所有基类的初始化?
如果只有一个基类,上述方法也适用。但是Python确实允许多重继承,你可能想要确保所有基类都被正确初始化。要做到这一点,你应该让每个基类调用init:
class Base1: def __init__(self): super(Base1, self).__init__() class Base2: def __init__(self): super(Base2, self).__init__() class Derived(Base1, Base2): def __init__(self): super(Derived, self).__init__()
如果我忘了为super调用init呢?
构造函数(__new__)在链中被调用(就像在c++和Java中一样)。创建实例后,只调用该实例的初始化器(__init__),不调用任何指向其超类的隐式链。
__new__
再添加一个带参数的例子:
class B(A): def __init__(self, x, y, z): A.__init__(self, x, y)
给定一个派生类B,它需要定义变量x, y, z,以及一个超类a,它需要定义变量x, y,你可以调用超类a的静态方法初始化,引用当前子类实例(self),然后是预期参数列表。