如何调用超级构造函数?

Mik*_*ike 330 python inheritance constructor class superclass

class A:
    def __init__(self):
        print("world")

class B(A):
    def __init__(self):
       print("hello")

B()  # output: hello
Run Code Online (Sandbox Code Playgroud)

在我使用超级构造函数的所有其他语言中隐式调用.如何在Python中调用它?我希望,super(self)但这不起作用.

Ign*_*ams 320

super()在新式类中返回类似父类的对象:

class A(object):
    def __init__(self):
        print("world")

class B(A):
    def __init__(self):
        print("hello")
        super(B, self).__init__()

B()
Run Code Online (Sandbox Code Playgroud)

  • 不,因为`self`实际上可能是`C`的实例,'B`的孩子. (108认同)
  • 只是为了好奇为什么`超级(B,自我)`需要提到B和自我?这不是多余的吗?不应该自己包含对B的引用吗? (75认同)
  • 关于`super()`](https://docs.python.org/3/library/functions.html#super)的文档,您应该能够编写`super().__ init __()`没有论点. (16认同)
  • @JojOatXGME:在3.x中,是的.2.x仍然需要参数. (13认同)
  • @Luc:那是因为该类声明不正确.看我的回答. (5认同)
  • @iuliux:在这种情况下,如果`self`是`B`的实例,那么`super(B,self).__ init __()`调用`A`和`super(A,self).__ init__中定义的方法. ()`调用`AA`中定义的方法.如果您正在编写可能是多重继承的类,则应始终包含对`super`构造函数的调用,但实际调用的代码取决于子类的继承决策.有关详细信息,请参见http://fuhm.net/super-harmful/. (2认同)
  • @IgnacioVazquez-Abrams 好的。也许您应该在回答中提到您使用的是 python 2.x?我对 python 比较陌生,我认为许多站点不写它们是使用 python 2 还是 python 3,这有点令人困惑。? (2认同)
  • @router:Python 2.x并没有在`super`中使用内省来确定相关的类和对象是什么,因此您必须传递它们。 (2认同)
  • 为什么最后调用的是super函数(我换了顺序,python只是忽略了super_init后面的代码,这是为什么?) (2认同)

Aid*_*mez 227

与其他答案一致,有多种方法可以调用超类方法(包括构造函数),但是在Python-3.x中,该过程已经简化:

Python的2.X

class A(object):
 def __init__(self):
   print "world"

class B(A):
 def __init__(self):
   print "hello"
   super(B, self).__init__()
Run Code Online (Sandbox Code Playgroud)

Python的3.X

class A(object):
 def __init__(self):
   print("world")

class B(A):
 def __init__(self):
   print("hello")
   super().__init__()
Run Code Online (Sandbox Code Playgroud)

super()现在相当于super(<containing classname>, self)该文档.


Gab*_*abe 53

使用Python 2.x旧式类,它将是这样的:

class A: 
 def __init__(self): 
   print "world" 

class B(A): 
 def __init__(self): 
   print "hello" 
   A.__init__(self)
Run Code Online (Sandbox Code Playgroud)

  • @kdbanman:这将适用于新式类,但使用新式类的原因之一是不必这样做.你可以使用`super`而不必直接命名你继承的类. (4认同)

Dan*_*ach 32

一种方法是调用A的构造函数并self作为参数传递,如下所示:

class B(A):
    def __init__(self):
        A.__init__(self)
        print "hello"
Run Code Online (Sandbox Code Playgroud)

这种风格的优点是它非常清晰.它调用A的构造函数.缺点是它不能很好地处理菱形继承,因为你最终可能会两次调用共享基类的构造函数.

另一种方法是使用super(),正如其他人所示.对于单继承,它与让您调用父的构造函数基本相同.

但是,super()在引擎盖下相当复杂,有时在多继承情况下可能是反直觉的.在正面,super()可用于处理菱形继承.如果你想知道super()所做的细节,那么我发现super()工作的最佳解释就在这里(虽然我不一定赞同那篇文章的观点).


Shi*_*hah 12

简答

super(DerivedClass, self).__init__()
Run Code Online (Sandbox Code Playgroud)

长答案

有什么作用super()

它采用指定的类名,找到它的基类(Python 允许多重继承)并__init__从左到右查找每个基类中的方法(在本例中)。一旦找到可用的方法,它就会调用它并结束搜索。

如何调用所有基类的 init?

如果您只有一个基类,则上述方法有效。但是 Python 确实允许多重继承,您可能希望确保所有基类都正确初始化。为此,您应该让每个基类调用 init:

class Base1:
  def __init__():
    super(Base1, self).__init__()

class Base2:
  def __init__():
    super(Base2, self).__init__()

class Derived(Base1, Base2):
  def __init__():
    super(Derived, self).__init__()
Run Code Online (Sandbox Code Playgroud)

如果我忘记为 super 调用 init 怎么办?

构造函数 ( __new__) 在链中被调用(如在 C++ 和 Java 中)。创建实例后,仅__init__调用该实例的初始化程序 ( ),而没有任何指向其超类的隐式链。


gal*_*007 5

仅添加一个带有参数的示例:

class B(A):
    def __init__(self, x, y, z):
        A.__init__(self, x, y)
Run Code Online (Sandbox Code Playgroud)

给定需要定义变量x,y,z的派生类B和需要定义x,y的超类A,您可以使用对当前子类实例的引用来调用超类A 的静态方法init(个体),然后是预期参数列表。