Python 方法名带双下划线会被覆盖吗?
看看这个。注意类 B
是如何重写类 A
的 a()
方法的。
In [1]: class A(object):
...: def __init__(self):
...: self.a()
...: def a(self):
...: print "A.a()"
...:
...:
In [2]: class B(A):
...: def __init__(self):
...: super(B, self).__init__()
...: def a(self):
...: print "B.a()"
...:
...:
In [3]: b = B()
B.a()
这没什么意外。
现在,再看看这个。注意现在被重写的方法是 __a()
。
In [7]: class A(object):
...: def __init__(self):
...: self.__a()
...: def __a(self):
...: print "A.__a()"
...:
...:
In [8]: class B(A):
...: def __init__(self):
...: super(B, self).__init__()
...: def __a(self):
...: print "B.__a()"
...:
...:
In [9]: b = B()
A.__a()
这个行为让我感到惊讶。
有没有人能解释一下为什么会调用 A.__a()
而不是 B.__a()
?
关于 __a
有什么 __special__
的地方吗?
更新:在阅读了Sean的回答后,我想看看能否重写这个名字被修改过的方法,结果是这样的:
In [11]: class B(A):
....: def __init__(self):
....: super(B, self).__init__()
....: def _A__a(self):
....: print "B._A__a()"
....:
....:
In [12]: b = B()
B._A__a()
2 个回答
1
In [1]: class A(object):
...: def __init__(self):
...: self.a()
...: def a(self):
...: print "A.a()"
...:
...: __str__ = a
...:
In [2]: class B(A):
...: def __init__(self):
...: super(B, self).__init__()
...: def a(self):
...: print "B.a()"
...:
...:
In [3]: b = B()
print str(b)
A.a()
你需要在B里面重新声明一下__str__
。
34
以__*开头的关键词是类的私有名称。
http://docs.python.org/reference/lexical_analysis.html#reserved-classes-of-identifiers
引用内容:
在类定义的上下文中使用的这类名称,会被改写成一种特殊的形式,以帮助避免基类和派生类之间“私有”属性的名称冲突。
私有名称改写(强调部分):
私有名称改写:当一个在类定义中出现的标识符以两个或更多的下划线开头,并且不以两个或更多的下划线结尾时,它被视为该类的私有名称。在生成代码之前,私有名称会被转换为一种更长的形式。这个转换会在名称前面加上类名,同时去掉前面的下划线,并在类名之前加一个下划线。例如,在名为Ham的类中出现的标识符
__spam
会被转换为_Ham__spam
。这个转换与标识符使用的语法上下文无关。如果转换后的名称非常长(超过255个字符),可能会进行截断。如果类名仅由下划线组成,则不会进行任何转换。
http://docs.python.org/reference/expressions.html#atom-identifiers
这意味着在后台,B.__a()
会被转换成类似B._B__a()
的形式。