我一直试图理解这个用例,我们经常从继承的类中调用基类构造函数,这样做的唯一目的是确保基类被初始化?或者,是否会有其他可能的用例?
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
super().__init__()
print('A.__init__')
答案 0 :(得分:2)
这样做的唯一目的是确保初始化基类?
是的,但你是什么意思,只是?
假设你的基类有理由存在,它必须做某事。
除非它只是一个方便的@staticmethod
函数集合,否则可能取决于它已被调用的__init__
,因为这就是类对象的工作方式。
即使你的基类今天有一个空的__init__
,如果将来发生变化,调用它也是明智的。
或者,是否会有其他可能的用例?
用例是确保正确初始化对象的基类部分。没有它,你就无法安全地调用任何的非静态方法。
原则上你的基类可以在__init__
中做一些棘手的事情(启动一个后台线程,或者用一些单例注册实例,或者......等等)。所以,是的,除了分配实例变量之外,还有其他影响,但这仍然是初始化该基类对象的一部分。
答案 1 :(得分:1)
在C ++或Java中,编译器将要求您调用基类构造函数(通过自动插入零参数调用或通过提供错误)。
Python要求您自己调用它,as it is written:
如果基类具有
__init__()
方法,则派生类的__init__()
方法(如果有)必须显式调用它以确保正确初始化实例的基类部分
原因是面向对象设计的原则。 A
"是-a" Base
,也可以等同地写成A
"有-a" Base
。除非您特别想干扰Base
的实现,否则必须允许按设计初始化对象。跳过构造函数会导致Base
对象未正确初始化,令任何期望它表现为Base
对象的人都会失望。
当覆盖构造函数之外的方法时,程序员可以自行决定委托基类实现或完全覆盖它。这仍然可能导致不正确的行为 - 我可以想到的几个API文档用#34;文档覆盖这个方法,你应该调用super"各种方法。
答案 2 :(得分:0)
这一点是初始化基类通常初始化的所有东西。例如,
class Base:
def __init__(self, number):
print('Base.__init__')
self.number = number
class A(Base):
def __init__(self, number, string):
super().__init__(number)
self.string = string
print('A.__init__')
在这个代码示例中,它更加明显。当A
调用基础构造函数时,基础构造函数将初始化所需的所有内容,例如self.number
。这样,A
的初始化函数的其余部分可以构建在基本初始化函数之上而无需任何重新类型化。在此示例中,通过在A
之上添加Base
,self.string
位于self.number
之上。