Python 的私有变量和方法

作者: , 共 1216 字 , 共阅读 0

今天写一段程序时遇到一个问题,查了好一会才搞清楚。代码可以简化为下面这个小代码:

#!/usr/bin/env python
# encoding: utf-8

def __p():
    print("called")

class X:
    def z(self):
        __p()

X().z() 

这段代码运行的时候会提示错误:

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    X().z()
  File "test.py", line 9, in z
    __p()
NameError: name '_X__p' is not defined

出现这个问题的原因是, python 使用一种 name mangling 技术,将类里出现的__membername替换成 _classname__membername,而且不管是不是通过类或self引用。在上面的例子中,__p被替换成了_X__p,从而出现找不到定义的错误。

Python 从语言角度并没有强制的私有化支持,通过这种方式来禁止直接访问。上面的 __p只能在全局函数里使用,类的__p也只能在本类里使用,其他类包括子类都无法直接访问。但只要知晓其规则,可以通过改名后的名字来访问:

class A():
    def __init__(self):
        self.__name = 'python' # 私有变量,翻译成 self._A__name = 'python'
    def __say(self):         # 私有方法,翻译成 def _A__say(self)
        print self.__name    # 翻译成 self._A__name

a = A()
print a.__name   # 访问私有属性,报错  no attribute '__name'
print a.__dict__ # 查询出实例a的属性的集合
print a._A__name # 这样,就可以访问私有变量了
a.__say()        # 调用私有方法,报错 no attribute '__say'
print dir(a)     # 获取实例的所有属性和方法
a._A__say()      # 这样,就可以调用私有方法了

但这种方法并无法让类访问一个模块全局定义的私有变量。另一方面,其它文件导入该模块(假设为test.py)后,(不在类里)还可以直接访问test.__p,并没有改名以及任何限制。

Q. E. D.

类似文章:
Python 提供很多语法糖,用起来非常方便。@dataclass 就是其中之一。
编程 » Python
在 Python 中,有时候为了获取当前运行的脚本的同目录下的另外一个文件,会这么写:
编程 » Python
imp.load_source在动态载入 python 模块时非常有用,但需要注意其特性。
编程 » Python
Python 在搜索模块时,依次搜索sys.path里的位置,直到找到模块为止。下面命令可以查看当前的搜索路径:
相似度: 0.141
编程 » pytorch, C++
目前 pytorch 已经升级到了 1.7.0 ,但在 ubuntu 20.04 下有一个非常诡异的 bug。为此,我们只能自己编译。
Pyhon 的抽象基类( abstruct base class )库abc定义了类似于 C++的纯虚函数的功能:
编程 » Python, 并行计算
核心就是threading.Thread
在 Python 中操作文件或字符串时,有时候会碰到 UnicodeDecodeError 异常:
IT » Python, Ubuntu
主要是update-alternatives命令的使用。
命令行参数的初步说明,请参考argparse 模块用法实例详解,写的很清晰而详细。
户外 » 玩水, 温榆河
最近玩水比较多,顺便关注了北京河流的水质。有些地方,一看就知道水质不好,但有些地方看着挺清的,其实水质也可能不好。最终找到了北京市生态环境局公布的北京市河流水质状况北京市湖泊水质状况
户外 » 下海, 东戴河
我们跟着绿野 9 家 22 人的大队伍,一起去东戴河玩耍。行程: