如何调用超级构造函数?

时间:2010-03-08 04:35:17

标签: python class inheritance constructor superclass

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

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

B()  # output: hello

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

7 个答案:

答案 0 :(得分:291)

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

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

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

B()

答案 1 :(得分:190)

与其他答案一致,有多种方法可以调用超类方法(包括构造函数),但是在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__()

<强> Python的3.x的

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

class B(A):
 def __init__(self):
   print("hello")
   super().__init__()
根据{{​​3}},

super()现在相当于super(<containing classname>, self)

答案 2 :(得分:51)

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

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

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

答案 3 :(得分:32)

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

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

这种风格的优点在于它非常清晰。它叫A的初始化者。缺点是它不能很好地处理菱形继承,因为你最终可能会两次调用共享基类的初始值。

另一种方法是使用super(),正如其他人所示。对于单继承,它与让您调用父级的初始化器基本相同。

然而,super()在引擎盖下相当复杂,有时在多继承情况下可能会违反直觉。在正面,super()可用于处理菱形继承。如果你想知道super()的含义,我发现super()的工作原理的最佳解释是here(虽然我不一定赞同那篇文章的意见)。

答案 4 :(得分:5)

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

class B(A):
    def __init__(self, x, y, z):
        A.__init__(self, x, y)

鉴于需要定义变量x,y,z的派生类B和需要定义x,y的超类A,您可以调用静态方法的 init 超类A,其中引用了当前子类实例(自身),然后是预期参数的列表。

答案 5 :(得分:2)

简短回答

super(DerivedClass, self).__init__()

长期回答

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__()

如果我忘记为超级调用init了怎么办?

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

答案 6 :(得分:1)

我使用以下公式扩展了之前的答案:

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

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

B()

这样您就不必在 super 的调用中重复该类的名称。如果您编写大量类,并希望使用与类名无关的初始化方法中的代码,它可以派上用场。