2

Python 的私有变量和方法

 1 year ago
source link: https://zhiqiang.org/coding/python-private-members.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Python 的私有变量和方法

作者: 张志强

, 2023-07-19

, 共 1216 字 , 共阅读 33 次

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

#!/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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK