Python中的私有成员

97 投票
10 回答
83504 浏览
提问于 2025-04-15 18:01

我该如何在Python中将方法和数据成员设置为私有?或者说,Python不支持私有成员吗?

10 个回答

14

在Python中,没有像其他编程语言那样的private或其他访问保护机制。不过,Python有一种约定,记录在Python风格指南中,用来告诉使用你类的人,哪些属性不应该被访问。

  • _单下划线开头:这是一个弱的“内部使用”标识符。例如,from M import *不会导入名字以下划线开头的对象。

  • 单下划线结尾_:按照约定用来避免与Python关键字冲突,比如Tkinter.Toplevel(master, class_='ClassName')

  • __双下划线开头:当给类的属性命名时,会触发名称改写(在类FooBar内部,__boo会变成_FooBar__boo;见下文)。

44

其他回答提供了技术细节。我想强调一下Python和像C++/Java这样的语言之间的哲学差异(我想你对这些语言应该有一定了解,因为你提到过它们)。

在Python(还有Perl)中,一般的态度是,属性的“隐私”更多是对程序员的一个请求,而不是编译器或解释器设立的高墙。这个想法在这封邮件中总结得很好,通常被称为“我们都是成年人”,因为它“假设”程序员有足够的责任感,不会随便去动内部的东西。前面的下划线就像是一个礼貌的提示,告诉你这个属性是内部的。

另一方面,如果你确实想访问内部内容来完成某些应用(比如像pydoc这样的文档生成器),你是可以这么做的。作为程序员,你需要知道自己在做什么,并且要正确地去做,而不是让语言强迫你按照它的方式去做事情。

109

9.6. 私有变量

在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 访问。

撰写回答