前几天同事问我关于如何外部访问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() # 可以从外修改私有变量 |
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 |
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()) |
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中使用了相同的类名称和空间。一定会造成私有变量的互相影响,所以再大型项目中需要谨慎使用