如何在Python中调用超级构造函数?

如何在Python中调用超级构造函数?,python,class,inheritance,constructor,superclass,Python,Class,Inheritance,Constructor,Superclass,在我使用过的所有其他语言中,超级构造函数都是隐式调用的。在Python中如何调用它?我希望super(self),但这不起作用。super()在新样式的类中返回类似于父对象的对象: 对于Python 2.x旧式类,应该是这样的: class A(object): def __init__(self): print("world") class B(A): def __init__(self): print("hello") sup

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

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


对于Python 2.x旧式类,应该是这样的:

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

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

B()

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

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

class B(A): 
 def __init__(self): 
   print "hello" 
   A.__init__(self)
这种风格的优点是非常清晰。它调用A的初始化器。缺点是它不能很好地处理菱形继承,因为最终可能会调用共享基类的初始化器两次

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


然而,super()在幕后要复杂得多,在多重继承的情况下有时会违反直觉。另一方面,super()可用于处理菱形继承。如果你想知道super()的本质,我找到的关于super()如何工作的最好解释是(尽管我不一定赞同那篇文章的观点)。

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

Python-2.x

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

class B(A):
 def __init__(self):
   print "hello"
   super(B, self).__init__()
Python-3.x

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

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

super()

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

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

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

简短回答

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

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

B()
长答案

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

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

B()
super()
做什么

它采用指定的类名,查找其基类(Python允许多重继承),并从左到右查找每个基类中的方法(在本例中为
\uuuu init\uuu
)。一旦找到可用的方法,它将调用该方法并结束搜索

如何调用所有基类的init

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

super(DerivedClass, self).__init__()
如果我忘记为超级用户调用init怎么办


构造函数(<代码>第x No.<代码>)在链中调用(如C++和java)。创建实例后,只调用该实例的初始化器(

\uuuu init\uuuu
),而不调用其超类的任何隐式链。

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

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

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

出于好奇,
super(B,自我)
要求同时提到B和self?这不是多余的吗?self不应该已经包含对B的引用吗?不,因为
self
可能实际上是
C
的一个实例,一个
B
的孩子@Luc:那是因为类被错误地声明了。请看我的答案。关于e> super()。\uuuu init\uuuuu()
wothout参数。@JojOatXGME:在3.x中,是的。2.x仍然需要参数。@kdbanman:这将适用于新样式类,但使用新样式类的原因之一是不必这样做。您可以使用
super
,而不必直接命名您继承的类。@Gabe这是最不重要的r使用
super
。但是如果您决定用
C
扩展
B
,并且使用
self,您将得到不定式递归
指向
B
而不是
A
。这将导致在子类
B
时出现无限递归错误。不要使用
self.\uuu class\uuuuu
键入(self)
,要么传入显式类(
B
),要么在Python 3中使用
super()
不带参数。当一个构造函数不带任何变量(忽略self)作为参数时,有必要这样调用它的构造函数吗?我的意思是,没有
A.\uu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(
self.stuff=[]
,例如。),如果不调用
A,可能会导致
B
的实例行为不正确。如果您的示例中所有三个类都定义了
\uuuuu new\uuuuu
,但没有使用
super()。\uu new\uuuuu()
,则
派生()
将调用
派生。
但不调用
Base1。
新的
Base2。
新的
新的
不调用其父对象的
新的
几乎是无用的,因为最终
对象。
新的是唯一真正创建任何事物的新实例的东西。派林建议g不带参数的Python 3样式super()。您应该强调,不使用派生类名的答案就是您想要的答案。例如(伪代码):
super()。\uuuuu init\uuuu(args…)
你应该接受艾丹·戈麦斯的答案。这会节省我们很多时间,因为它在python 2和python 3中都有答案。python 2不再得到官方支持。他的答案也在5年后出现。@Mike我认为列出python的答案仍然有价值