关于python:如何调用super constructor?

How to invoke the super constructor?

1
2
3
4
5
6
7
8
9
class A:
    def __init__(self):
        print("world")

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

B()  # output: hello

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


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

1
2
3
4
5
6
7
8
9
10
class A(object):
    def __init__(self):
        print"world"

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

B()


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

Python 2.x

1
2
3
4
5
6
7
8
class A(object):
 def __init__(self):
   print"world"

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

Python 3.x

1
2
3
4
5
6
7
8
class A(object):
 def __init__(self):
   print("world")

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

根据文件,super()现在等同于super(, self)


对于python 2.x旧样式类,应该是:

1
2
3
4
5
6
7
8
class A:
 def __init__(self):
   print"world"

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


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

1
2
3
4
class B(A):
    def __init__(self):
        A.__init__(self)
        print"hello"

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

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

然而,super()在引擎盖下要复杂得多,并且有时在多个继承情况下可能是反直觉的。另一方面,super()可以用来处理菱形继承。如果你想知道super()的具体功能,我找到的关于super()工作原理的最好解释就在这里(尽管我不一定赞同那篇文章的观点)。


简短回答

1
super(DerivedClass, self).__init__()

长回答

super()是做什么的?

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

如何调用所有基类的init?

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

1
2
3
4
5
6
7
8
9
10
11
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怎么办?

没有调用基类的__init__。没有像C++和Java那样的隐式构造函数调用。


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

1
2
3
4
5
6
7
8
9
10
class A(object):
 def __init__(self):
   print"world"

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

B()

这样就不必在调用super时重复类的名称。如果您要对大量类进行编码,并且希望使构造函数方法中的代码独立于类名,那么它就可以派上用场。