Python中的私有成员
我该如何在Python中将方法和数据成员设置为私有?或者说,Python不支持私有成员吗?
10 个回答
在Python中,没有像其他编程语言那样的private
或其他访问保护机制。不过,Python有一种约定,记录在Python风格指南中,用来告诉使用你类的人,哪些属性不应该被访问。
_单下划线开头:这是一个弱的“内部使用”标识符。例如,
from M import *
不会导入名字以下划线开头的对象。单下划线结尾_:按照约定用来避免与Python关键字冲突,比如
Tkinter.Toplevel(master, class_='ClassName')
。__双下划线开头:当给类的属性命名时,会触发名称改写(在类FooBar内部,__boo会变成_FooBar__boo;见下文)。
其他回答提供了技术细节。我想强调一下Python和像C++/Java这样的语言之间的哲学差异(我想你对这些语言应该有一定了解,因为你提到过它们)。
在Python(还有Perl)中,一般的态度是,属性的“隐私”更多是对程序员的一个请求,而不是编译器或解释器设立的高墙。这个想法在这封邮件中总结得很好,通常被称为“我们都是成年人”,因为它“假设”程序员有足够的责任感,不会随便去动内部的东西。前面的下划线就像是一个礼貌的提示,告诉你这个属性是内部的。
另一方面,如果你确实想访问内部内容来完成某些应用(比如像pydoc这样的文档生成器),你是可以这么做的。作为程序员,你需要知道自己在做什么,并且要正确地去做,而不是让语言强迫你按照它的方式去做事情。
在Python中,没有真正的“私有”实例变量,也就是说,除了对象内部,外部无法访问这些变量。不过,大多数Python代码遵循一个约定:如果一个名字前面有一个下划线(比如说 _spam),那么它应该被视为不公开的部分(无论是函数、方法还是数据成员)。这意味着它是实现细节,可能会随时改变。
由于有合理的需求来使用类私有成员(主要是为了避免与子类中定义的名字冲突),Python提供了一种有限的支持机制,叫做名字改编(name mangling)。任何形式为 __spam 的标识符(至少两个前导下划线,最多一个后导下划线)会被文本上替换为
_classname__spam
,其中 classname 是当前类的名字,前面的下划线会被去掉。这种改编不考虑标识符的语法位置,只要它出现在类的定义中。
所以,例如,
class Test:
def __private_symbol(self):
pass
def normal_symbol(self):
pass
print dir(Test)
将输出:
['_Test__private_symbol',
'__doc__',
'__module__',
'normal_symbol']
__private_symbol
应该被视为一个私有方法,但仍然可以通过 _Test__private_symbol
访问。