漫话 python 类的私有方法

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

关于xu xc

工作两年了,有点懒,完了在写吧
此条目发表在python分类目录,贴了, 标签。将固定链接加入收藏夹。