1 Private Variable and Private Method
2 Python 不象 Java 那样, 通过 private 关键字创建私有属性, python 通过更简洁的实现了'私有属性', 从而避免了子类意外覆盖私有属性.
3 举个例子来说, 现在编写一下儿名字叫 Robot 的类,并实现了一个名字为 fighting 的属性。
4 接着又人编写了一个叫 Camaro 的类, 并继承了 Robot 类, 并在其中构造了 fighting 的属性, 这个时候 Robot 的 fighting 属性被覆盖了.
5 而恰巧 Robot 类的编写者的意图是 - 不允许所有 Robot 的子类访问 fighting(可能为了世界和平), 显然 Camaro 这个子类破坏了这一点.
6
7 为了避免这种情况, Robot 类的编写者可以以 __fighting (或者 __fighting_) 来命名要私自属性(声明成成私有属性).
8 这时 Python 的解释器会该属性 '修饰' 后再添加到 __dict__ 属性中, 该例中会变成 _Robot__fighting, 而不是 __fighting (原形式)
9 Python 的这种特性被称为 name mangling.
10 注, 名称改写(name mangling),Python 解释器在运行时自动把私有属性 __x (或 __x_)重命名为 _MyClass__X (或 _MyClass__X_)
11
12 以上文字所对应的例子,
13 class Robot(object):
14 __RB = 3
15 __RB_ = 5
16 def __fighting(self):
17 print('This is \'_MyClass__X\' format')
18
19 def __fighting_(self):
20 print('This is \'_MyClass__X_\' format')
21
22 def func(self):
23 print('Called via - A')
24
25 class Camaro(Robot):
26 def func(self):
27 print('Called via - B')
28
29 if __name__ == "__main__":
30 print(Robot.__dict__) #1
31 a = Camaro()
32 a.func() #2
33 print(Camaro.__mro__) #3
34 super(Camaro,a).func() #3
35 a._Robot__fighting() #4
36 a._Robot__fighting_() #4
37 a.__fighting #5
38
39 Output,
40 {'__module__': '__main__', '_Robot__RB': 3, '_Robot__RB_': 5,'_Robot__fighting': <function Robot.__fighting at 0x039C6300>,
41 '_Robot__fighting_': <function Robot.__fighting_ at 0x039C62B8>,
42 'func': <function Robot.func at 0x039C6270>, ...}
43 #1 |^ 添加到 __dict__ 中的是 '_MyClass__X' 或者 '_MyClass__X_' - name mangling
44 Called via - B #2 子类的中方法覆盖了父类中的'同名'方法
45 (<class '__main__.Camaro'>, <class '__main__.Robot'>, <class 'object'>) #3 MRO __mro__
46 Called via - A #3 super 指的并不一定是'父类', 而是 MRO 中的'下一个' ******
47 This is '_MyClass__X' format #4 name mangling ; 知道 name mangling 规则后 可以 hack 私有属性
48 This is '_MyClass__X_' format #4 name mangling ; 知道 name mangling 规则后 可以 hack 私有属性
49 a.__fighting
50 AttributeError: 'Camaro' object has no attribute '__fighting' #5 常规方法调用属性报错(AttributeError), 因为 __dict__ 没有相应属性