python super calling child methods
关于
当从子类调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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() |
但失败的是
1 2 3 4 5 6 7 8 9 10 11 | 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' |
在这里,我调用
这可能是直观的,也可能不是直观的,但是当我希望
如果代码必须调用不能重写的特定私有方法,请使用以两个下划线开头的名称:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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通过添加类名(加上下划线)来"改变"这种方法名,以最小化子类用自己的版本覆盖它们的机会。
《Pep8 Python风格指南》对私有名称管理有这样的描述:
If your class is intended to be subclassed, and you have attributes
that you do not want subclasses to use, consider naming them with
double leading underscores and no trailing underscores. This invokes
Python's name mangling algorithm, where the name of the class is
mangled into the attribute name. This helps avoid attribute name
collisions should subclasses inadvertently contain attributes with the
same name.Note 1: Note that only the simple class name is used in the mangled
name, so if a subclass chooses both the same class name and attribute
name, you can still get name collisions.Note 2: Name mangling can make certain uses, such as debugging and
__getattr__() , less convenient. However the name mangling algorithm
is well documented and easy to perform manually.Note 3: Not everyone likes name mangling. Try to balance the need to
avoid accidental name clashes with potential use by advanced callers.
您需要使用
如果我们通过
- 我们叫
super(B,self).__init__ ,也就是说,A.__init__ 。 - 我们称之为
self.a() ,也就是说,B.a() , - 使用
self.bnum 。
除了
在这种情况下,在调用
1 2 3 4 | class B(A): def __init__(self): self.bnum=3 super(B, self).__init__() |
在进入名称混乱的黑暗路径之前,您可能想花些时间组织子类的代码:应该在父类之前执行,初始化一些特殊变量,还是在父类之后执行,以替换一些默认值?
考虑这个电话:
1 2 3 | class B(A): def __init__(self): A.__init__(self) |
当你叫