如图所示,B
类继承了 A
类;
当实例化对象时,B
类中没有构造函数, 应该调用父类的构造函数 __init__
但是里边的 self.__pirv()
为啥调用到父类 A
的 __priv
, 而 self.pub()
又调到 B
中的 pub
求解?
ringa_lee2017-04-18 10:30:50
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 __
大家讲道理2017-04-18 10:30:50
After thinking about this question for a while, here’s my understanding:
class A(object):
def __init__(self):
self.__priv() # _A__priv()
self.pub()
def __priv(self):
print("private A")
def pub(self):
print("public A")
class B(A):
def __init__(self):
self.__priv() # 调用_B__priv()对比
super(B, self).__init__() # 在这里显式调用父类的`__init__()`方法
def __priv(self):
print("private B")
def pub(self):
print("public B")
if __name__ == '__main__':
b = B()
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.
巴扎黑2017-04-18 10:30:50
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
A
)
dir(b)
So at the end you will see
__init__
(從 A
A
)_A__priv
(從 A
A
)_B__priv
public
__init__
被呼叫時, 會調用 _A__priv
, 而 B
Finally, when
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() # 防都防不住
The anti-fool
mechanism is not aThe mechanism to prevent accidental
access is not a mechanism to preventBut 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
would be a better choice.const
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 use
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🎜Questions I answered: Python-QA