In Python, method names starting from __ are not private. __ means to let Python do name mangling. The result of name mangling is _A__priv. You should not overwrite using this method. If you want a subclass to overwrite a method, you can only use _, not __
Call __init__()方法时,从子类B本身中查找pub()方法,显然是存在的,因此会调用B类自身的pub()方法;然而在调用__priv()方法时,由于Python对私有成员进行了名称改编,你实际调用的是_A__priv()方法,而B类中并没有这个方法,有的只有_B__priv(),因此调用父类A中的_A__priv() on the instance of the subclass, resulting in this result. This is my personal understanding, please correct me if I am wrong, thank you.
As for the problem itself, @Xavier and @Christoph have already explained it in detail
If you still don’t understand, you can try this:
Original code:
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()
Do it manually 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()
All properties of
B 在這裡繼承了 A include:
__init__
_A__priv
public
And B defined it by itself:
_B__priv
public (此處覆寫了 A 的 public (here overridden
of A)
dir(b)So at the end you will see
which contains:
__init__ (從 A
(inherited from A)
_A__priv (從 A
(inherited from A)
_B__priv
(your own definition)
public
(your own definition)
__init__ 被呼叫時, 會調用 _A__priv, 而 BFinally, when
is called, will be called, and
does have this method in it
I would like to add that Python itself does not have a real private mechanism, because people who understand name mangling can access attributes starting with a double underscore. For example, I can easily write:
a = A()
a._A__priv() # 防都防不住
Simply speaking, this mechanism is:
The anti-fool
mechanism is not a
anti-villain
mechanism,
The mechanism to prevent accidental
access is not a mechanism to prevent
deliberate access
But not everyone thinks this mechanism is good (I personally don’t like it, using a double underscore to start the name is troublesome and not much practical help), so you can find it in a lot of python code: People often use
single Bottom line
The protection method at the beginning is a recognized practice (Note 1). It is enough to prevent fool-proofing for slightly experienced programmers, and there will be no additional effects or unexpected situations.
Ian Bicking has a passage that says this (Ian Bicking is a Python master, I saw this passage in Luciano Ramalho’s Fluent Python):
Never use two base lines in front of it. This is infuriatingly selfish, and if you don't want to cause a name conflict (Note 2), you can reshape the name explicitly (eg: _MyThing_blahblah). Essentially this is the same as using The double bottom line is the same thing, but it is public, while the double bottom line is a private behavior._priv
So my suggestion is, using
would be a better choice.constNote 1: Attributes starting with a single underscore will not have any special properties. It is just a symbolic method that relies on the consensus of Python programmers. Just like some languages will use
to mark constants, and We can also just rely on the consensus that
constants should be named in uppercase letters
to avoid unexpected situations🎜
🎜Note 2: The reason why you want to protect attributes with private properties is that the most common reason is accidental access caused by name conflicts🎜
In Python, method names starting from __ are not private. __ means to let Python do name mangling. The result of name mangling is _A__priv. You should not overwrite using this method. If you want a subclass to overwrite a method, you can only use _, not __
After thinking about this question for a while, here’s my understanding:
Call
__init__()
方法时,从子类B
本身中查找pub()
方法,显然是存在的,因此会调用B
类自身的pub()
方法;然而在调用__priv()
方法时,由于Python对私有成员进行了名称改编,你实际调用的是_A__priv()
方法,而B
类中并没有这个方法,有的只有_B__priv()
,因此调用父类A
中的_A__priv()
on the instance of the subclass, resulting in this result. This is my personal understanding, please correct me if I am wrong, thank you.As for the problem itself, @Xavier and @Christoph have already explained it in detail
If you still don’t understand, you can try this:
Original code:
Do it manually name mangling:
All properties ofB
在這裡繼承了A
include:__init__
_A__priv
public
And
B
defined it by itself:_B__priv
ofpublic
(此處覆寫了A
的public
(here overriddenA
)dir(b)
So at the end you will see
(inherited from__init__
(從A
A
)
(inherited from_A__priv
(從A
A
)
(your own definition)_B__priv
(your own definition)public
__init__
被呼叫時, 會調用_A__priv
, 而B
Finally, whenwill be called, and
does have this method in it
The anti-fool
mechanism is not aThe mechanism to prevent accidental
access is not a mechanism to preventsingle Bottom line
The protection method at the beginning is a recognized practice (Note 1). It is enough to prevent fool-proofing for slightly experienced programmers, and there will be no additional effects or unexpected situations.Never use two base lines in front of it. This is infuriatingly selfish, and if you don't want to cause a name conflict (Note 2), you can reshape the name explicitly (eg: _MyThing_blahblah). Essentially this is the same as using The double bottom line is the same thing, but it is public, while the double bottom line is a private behavior.
_priv
So my suggestion is, using
would be a better choice.
to mark constants, and We can also just rely on the consensus thatconst
Note 1: Attributes starting with a single underscore will not have any special properties. It is just a symbolic method that relies on the consensus of Python programmers. Just like some languages will useconstants should be named in uppercase letters
to avoid unexpected situations🎜 🎜Note 2: The reason why you want to protect attributes with private properties is that the most common reason is accidental access caused by name conflicts🎜Questions I answered: Python-QA