关于super()
的用法有很多问题,但似乎没有一个能回答我的问题。
从子类调用super().__init__()
时,超级构造函数中的所有方法调用实际上都是从子类中获取的。考虑以下类结构:
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
中的所有方法都只能访问在那里实现的函数时,我必须做什么?
考虑这个电话:
这就是当您调用
super().__init__()
时发生的情况。这反过来又调用self.a()
,这当然是类B
的函数a
,而不是A
,因为self
是类B
。正如Martijn所说,您可以使用双下划线名称,或者显式地使用类名,但否则就不可能从超类调用重写的方法。您需要使用
A.a(self)
,而不是调用self.a()
。但是对于一个特定类上的所有方法,这并不常见,而且您应该重新评估B
是否应该继承自A
。如果代码有调用无法重写的特定私有方法,请使用以两个下划线开头的名称:
Python"mangles"通过在类名(加下划线)中添加这样的方法名,以尽量减少子类用自己的版本覆盖它们的可能性。
PEP 8 Python Style Guide有这样一个关于私名损坏的说法:
相关问题 更多 >
编程相关推荐