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__ 没有相应属性