没有关于使用许多问题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
只能够访问那里执行的功能?
如果你的代码必须调用不能被重写特定的私有方法,使用两个下划线开头的名称:
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)
Python的“轧液”在类名(加下划线)添加到最小化的子类覆盖它们自己版本的机率这种方法名。
该PEP 8 Python的风格指南是这样说的关于私人名字改编:
如果你的类是为了被继承,你有你不想子类使用,可以考虑用双下划线开头命名它们的属性和没有尾随下划线。 这将调用Python的名字改编算法,其中类的名称错位到属性名称。 这有助于避免属性名称冲突应子无意中包含具有相同名称的属性。
注1:请注意,只有简单的类名在错位的名称中使用,因此,如果一个子类都选了相同的类名和属性名,你仍然可以得到名称冲突。
注2:名称重整可以使某些用途,如调试和__getattr__()
不太方便。 然而,名称重整算法是有据可查的,易于手动执行。
注3:不是每个人都喜欢的名字改编。 尝试平衡的必要性,以避免意外的名称冲突与先进的呼叫者的潜在用途。
而不是调用self.a()
你需要使用Aa(self)
。 但是,这不是常见的在特定类的所有方法做, 你应该重新评估是否B
应继承A
。
考虑这个调用:
class B(A):
def __init__(self):
A.__init__(self)
这是发生了什么,当你调用super().__init__()
这,反过来,调用self.a()
这当然是的函数a
类的B
而不是A
因为self
是类的B
。 正如马亭说,你可以使用双下划线的名称,或者明确地使用类名,否则就不可能调用从超类的覆盖方法。
如果我们通过的instanciation步骤B
:
- 我们称之为
super(B,self).__init__
,那就是, A.__init__
- 这就要求
self.a()
也就是Ba()
在我们的情况下, - 它采用
self.bnum
除了bnum
尚未定义尚未...所以, AttributeError
。
对于这种特殊的情况下,它只是足以定义你bnum
在B.__init__
调用之前 super(B,self).__init__
class B(A):
def __init__(self):
self.bnum=3
super(B, self).__init__()
去之前名字改编的黑暗,黑暗的道路,您可能希望只取来组织你的子类的代码的时间:应前父母的进行,初始化一些特殊变量,或者在父母的,要更换一些默认?