关于python的继承的一个疑问
迷茫
迷茫 2017-04-18 10:28:50
0
3
887

如图所示,B 类继承了 A 类;

当实例化对象时,B 类中没有构造函数, 应该调用父类的构造函数 __init__

但是里边的 self.__pirv() 为啥调用到父类 A__priv, 而 self.pub() 又调到 B 中的 pub

求解?

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

reply all(3)
左手右手慢动作

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:

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.

巴扎黑

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 (此處覆寫了 Apublic (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.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

    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🎜

    Questions I answered: Python-QA

    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template