class A:
def __init__(self):
self.__priv() # 等等改成 self._A__priv()
self.public()
def __priv(self): # 等等改成 def _A__priv(self):
print('private of A')
def public(self):
print('public of A')
class B(A):
def __priv(self): # 等等改成 self._B__priv(self):
print('private of B')
def public(self):
print('public of B')
b = B()
自行手动进行 name mangling:
class A:
def __init__(self):
self._A__priv()
self.public()
def _A__priv(self):
print('private of A')
def public(self):
print('public of A')
class B(A):
def _B__priv(self):
print('private of B')
def public(self):
print('public of B')
b = B()
B 在這裡繼承了 A 的所有属性包含:
__init__
_A__priv
public
而 B 自己定义了:
_B__priv
public (此處覆寫了 A 的 public (此处覆写了 A 的
)
dir(b)所以最后你会看到
里面有:
__init__ (從 A
(从 A 继承的)
_A__priv (從 A
(从 A 继承的)
_B__priv
(自己定义的)
public
(自己定义的)
__init__ 被呼叫時, 會調用 _A__priv, 而 B最后当
被呼叫时, 会调用 , 而
里面的确有这个方法
啰唆补充一下, Python 本身并没有真正的 private 机制, 因为了解 name mangling 的人就能对以双底线开头的属性做存取, 比如说我可以很轻易地写出:
在Python从__开始的方法名称不是private,__的意思就让Python做name mangling,name mangling的结果就是_A__priv。这样的方法你应该不要overwrite。如果你想让子类overwrite一个方法你只用_,不用__
想了一下这个问题,我是这样理解的:
在子类的实例调用
__init__()
方法时,从子类B
本身中查找pub()
方法,显然是存在的,因此会调用B
类自身的pub()
方法;然而在调用__priv()
方法时,由于Python对私有成员进行了名称改编,你实际调用的是_A__priv()
方法,而B
类中并没有这个方法,有的只有_B__priv()
,因此调用父类A
中的_A__priv()
,于是产生了这样的结果。这是我个人的理解,如果有误欢迎指正,谢谢。关于问题本身, @Xavier 和 @Christoph 已经有详细的说明了
如果你还不明白可以试着这样做:
原本的代码:
自行手动进行 name mangling:
B
在這裡繼承了A
的所有属性包含:__init__
_A__priv
public
而
B
自己定义了:_B__priv
)public
(此處覆寫了A
的public
(此处覆写了A
的dir(b)
所以最后你会看到
(从__init__
(從A
A
继承的)
(从_A__priv
(從A
A
继承的)
(自己定义的)_B__priv
(自己定义的)public
__init__
被呼叫時, 會調用_A__priv
, 而B
最后当, 而
里面的确有这个方法
防呆
的机制, 不是个防止意外
存取的机制, 不是个防止单个底线
开头的保护方式, 这种做法是个公认的惯例(注1), 对于稍有经验的程序员来说足以防呆, 且不会有任何额外的效果和意外的状况发生永远不要在前面使用两个底线. 这是很让人生气的自私行为, 如果你不希望造成名称冲突(注2), 可以明确地重整名称(例如: _MyThing_blahblah). 实质上这与使用双底线是同一件事情, 不过他是公开的, 双底线是私下的行为.
_priv
所以我的建议是, 使用
会是更好的选择.
来标明常量, 而我们也可以仅依赖const
注1: 以单底线开头的属性不会具有任何特殊的性质, 他仅仅是依靠Python 程序员的共识而产生的具有象征意义的符号性手法, 就好像有些语言会使用常量使用大写命名
的共识来避免意外的状况发生🎜 🎜注2: 之所以想要以 private 性质来保护属性, 最常见的就是因为名称冲突引起的意外存取🎜我回答过的问题: Python-QA