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

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

B()  # output: hello

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

4

7 回答 7

394

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

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

class B(A):
 def __init__(self):
   print "hello"
   super(B, self).__init__()
于 2015-10-17T20:17:54.160 回答
375

super()在新式类中返回一个类父对象:

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

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

B()
于 2010-03-08T04:43:13.447 回答
53

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

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

class B(A): 
 def __init__(self): 
   print "hello" 
   A.__init__(self)
于 2010-03-08T04:48:00.900 回答
37

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

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

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

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

然而,super() 在底层要复杂得多,有时在多重继承情况下可能违反直觉。从好的方面来说,super() 可用于处理菱形继承。如果您想了解 super() 的具体功能,我找到的关于 super() 工作原理的最佳解释就是这里(尽管我不一定赞同那篇文章的观点)。

于 2010-03-08T05:01:49.437 回答
15

简答

super(DerivedClass, self).__init__()

长答案

做什么super()

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

如何调用所有基类的 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__()

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

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

于 2018-11-28T02:39:25.733 回答
14

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

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

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

于 2019-07-31T09:49:20.247 回答
-1

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

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

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

B()

这样您就不必在调用super时重复类的名称。如果您正在编写大量类,并且希望在初始化方法中使您的代码独立于类名,它会派上用场。

于 2015-11-20T10:46:46.320 回答