何时使用super(Baseclass,self).__init__?

3

以下这段Python代码应该在何时使用? (假设Baseclass继承自Parent class,而Parent class又在__init__()方法中初始化了一些变量)

class Baseclass(Parent):
    def __init__(self, some_arg):
        self.some_arg = some_arg
        super(Baseclass, self).__init__()

这段代码是否让Parent类中__init__方法中定义的所有局部变量在Baseclass中可访问?这有什么重要意义吗?

“variables definied in __init__”是什么意思?您是指实例属性还是局部变量? - Lucas Kahlert
我指的是本地变量,例如self.some_variable = some_variable。 - kartikeykant18
1个回答

6

super可以避免代码重复;一个复杂的__init__不需要被复制/粘贴到你的继承类中。它还使MRO按照应有的方式工作,这样如果你使用多重继承,它将正确地工作。

这样做的一个原因是确保所有继承对象都具有某些来自父类缺少的属性。如果你只是编写一个新的__init__,除非你重复你的代码,否则它们将没有这些属性。例如:

>>> class A(object):
...     def __init__(self, x):
...             self.x = x
... 
>>> class B(A):
...     def __init__(self, y):
...             self.y = y
... 
>>> Stick = B(15)
>>> Stick.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'B' object has no attribute 'x'
>>>

__init__期间不调用super将完全覆盖整个方法。在这里调用super可以确保两个变量存在于继承类中。
>>> class C(A):
...     def __init__(self, x, y):
...             super(C, self).__init__(x)
...             self.y = y
... 
>>> Dave = C(15, 22)
>>> Dave.x
15
>>> Dave.y
22
>>>  

请注意在super调用中,x被传递给__init__()调用,但是self在代码的super(C,self)部分被处理。
编辑:TyrantWave也正确指出,在__init__之外,super也非常有用。以一个简单的foo方法为例子。
class Parent(object):
    def foo(self):
        return "I say foo!"

继承类可能只想修改此函数的输出,而不是完全重写它。因此,我们不要重复自己并重复编写相同的代码,只需调用 super 来获取父类的返回值,然后处理数据并返回子类修改后的结果。
class Child(Parent):
    def foo(self):
        parent_result = super(Child, self).foo()
        return "I'm a child!! %s" % parent_result

在上面的代码中,调用super会返回Parent类中foo()方法的值,然后Child类会进一步处理数据并将其返回。
>>> Alan = Parent()
>>> Stan = Child()
>>> Alan.foo()
'I say foo!'
>>> Stan.foo()
"I'm a child!! I say foo!"
>>> 

1
还要注意的是,你不仅可以从super中调用__init__super(B, self).func(args)将使用argsA中调用func - TyrantWave
1
这是正确的,也是一个很好的使用例子 - 我会更新我的答案以包含它。 - user890167

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接