前几天同事问我关于如何外部访问python私有属性的问题,当时觉得私有属性不应该被外部访问。但是回过头来想一下python私有属性的实现却是很有意思。
先看这段代码
class A(object): _a = "this is _a" __a = "this is __a" def set_private(self, a1, a2): self._a = a1 self.__a = a2 def read_private(self): print(self._a, self.__a, self._A__a) a1 = A() print(a1._a) print(hasattr(a1.__a)) # => False; 没有__a这个属性 print(a1._A__a) # 可以成功读取私有变量 a1._A__a = None a1.read_private() # 可以从外修改私有变量 |
貌似python对私有变量的实现就是改了下变量名啊?看着貌似挺简单的,但是聪明的你一定发现了问题,重命名变量如果重名咋办?
看这段例子:
class A(object): _a = "this is _a" __a = "this is __a" _A__a = "this is _A__a" def set_private(self, a1, a2=None, a3=None): self._a = a1 if a2: self.__a = a2 if a3: self._A__a = a3 def read_private(self): print(self._a, self.__a, self._A__a) a2 = A() a2.read_private() # 期望结果是 (this is _a, this is __a, this is _A__a) #=> (this is _a, this is _A__a, this is _A__a) ## 说明python的私有变量果然只是简单测重命名,规则就是"_{class_name}__{private_name}" a2.set_private(0, 1) print(a2.read_private()) #=> 0 1 1 a2._A__a = 2 print(a2.read_private()) #=> 0 2 2 |
不难看出,类方法内修改__private_name 等价于外部直接访问"_{class_name}__{private_name}"
看似很美好,但如果出现重名的类呢?
class A(object): __p1 = 1 __p = "A1" def get1(self): print(self.__p, self.__p1) A1 = A class A(object): __p = "A2" __p2 = "2" def get2(self): print(self.__p, self.__p2) A2 = A print(A1, A2) class B(A1, A2): _A__p = "B" b = B() print(b.get1()) print(b.get2()) |
不难发现python私有变量只是一种访问的语法糖。在某些情况下,比如利用type函数动态生成的class中使用了相同的类名称和空间。一定会造成私有变量的互相影响,所以再大型项目中需要谨慎使用
您必须登录才能发表评论。