有关 super()
的使用的问题很多,但它们似乎都没有回答我的问题 .
从子类调用 super().__init__()
时,超级构造函数中的所有方法调用实际上都来自 subclass . 考虑以下类结构:
class A(object):
def __init__(self):
print("initializing A")
self.a()
def a(self):
print("A.a()")
class B(A):
def __init__(self):
super().__init__()
# add stuff for B
self.bnum=3 # required by B.a()
def a(self):
print("B.a(), bnum=%i"%self.bnum)
b=B()
失败了
initializing A
Traceback (most recent call last):
File "classmagic.py", line 17, in
b=B()
File "classmagic.py", line 11, in __init__
super().__init__()
File "classmagic.py", line 5, in __init__
self.a()
File "classmagic.py", line 15, in a
print("B.a(), bnum=%i"%self.bnum)
AttributeError: 'B' object has no attribute 'bnum'
这里我调用 B()
中的超级构造函数来初始化一些基本结构(其中一些作为自己的函数 a()
执行) . 但是,如果我也覆盖 a()
函数,则在调用 A
的构造函数时会使用此实现,因为 A
对 B
一无所知并且可能使用不同的内部变量 .
这可能是也可能不直观,但当我希望 A
中的所有方法只能访问在那里实现的函数时,我该怎么做?
4 回答
如果您的代码必须调用无法覆盖的特定私有方法,请使用以两个下划线开头的名称:
Python "mangles"这样的方法名称通过添加类名(加上下划线)来最小化子类用自己的版本覆盖它们的机会 .
PEP 8 Python Style Guide有关于私人名称修改的说法:
而不是调用
self.a()
,你需要使用A.a(self)
. 但是这对于特定类的 all methods 并不常见,你应该重新评估B
是否应该从A
继承 .考虑这个电话:
当你拨打
super().__init__()
时会发生什么 . 反过来,这会调用self.a()
,这当然是B
类的函数a
而不是A
,因为self
属于B
类 . 正如Martijn所说,你可以使用双下划线名称,或明确使用类名,但是否则不可能从超类中调用重写方法 .如果我们通过
B
的实例化步骤:我们称之为
super(B,self).__init__
,即A.__init__
在我们的例子中调用
self.a()
,即B.a()
,使用
self.bnum
除了
bnum
尚未定义...所以,AttributeError
.对于这种特殊情况,只需在
B.__init__
before 中调用super(B,self).__init__
即可定义bnum
在走向黑暗,黑暗的名称修改路径之前,您可能只想花时间来组织子类的代码:它应该在父代之前执行,初始化一些特殊变量,还是在父代之后执行,以替换一些默认值?