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

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

B()  # output: hello

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


当前回答

与其他答案一致,有多种方法可以调用超类方法(包括构造函数),但是在Python 3中,这个过程被简化了:

Python 3

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

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

Python 2

在Python 2中,必须调用稍微详细一点的版本super(<包含类名>,self),这相当于文档中的super()。

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

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

其他回答

简短的回答

super(DerivedClass, self).__init__()

长回答

super()做什么?

它接受指定的类名,找到它的基类(Python允许多重继承),并从左到右在每个基类中查找方法(在本例中为__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__),不调用任何指向其超类的隐式链。

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

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

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

B()

这样就不必在调用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作为参数传递,如下所示:

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

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

另一种方法是使用super(),就像其他人展示的那样。对于单继承,它所做的基本上与让你调用父类的初始化式相同。

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