有人很好心地向我解释了 __method() 的名称修饰,但是由于还有很多需要帮助的人,所以我不想再打扰他了。我想知道是否有人能进一步说明它们之间的区别。
例如,我不需要名称修饰,但是如果使用 _,那么 instance._method() 是否无法被外部访问?或者它只是通过使其唯一来防止其他变量被覆盖?我不需要隐藏我的内部方法,但是由于它们特定于使用,我不希望它们在类外被使用。
有人很好心地向我解释了 __method() 的名称修饰,但是由于还有很多需要帮助的人,所以我不想再打扰他了。我想知道是否有人能进一步说明它们之间的区别。
例如,我不需要名称修饰,但是如果使用 _,那么 instance._method() 是否无法被外部访问?或者它只是通过使其唯一来防止其他变量被覆盖?我不需要隐藏我的内部方法,但是由于它们特定于使用,我不希望它们在类外被使用。
从PEP 8中:
_single_leading_underscore
:弱"内部使用"指示符。例如:
from M import *
不会导入名称以下划线开头的对象。
single_trailing_underscore_
:惯例上用于避免与Python关键字冲突,例如:
Tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore
:当命名类属性时,触发名称 编写(在类FooBar
内,__boo
变成_FooBar__boo
;见下文)。__double_leading_and_trailing_underscore__
:"魔法"对象或属性 存在于用户可控的命名空间中。例如__init__
,__import__
或__file__
。永远不要发明这样的名称;只能按照文档使用。
另外,来自David Goodger的Code Like a Pythonista:
属性:
interface
,_internal
,__private
但尽量避免使用
__private
。我从来不用它。相信我,如果你使用了它,你以后会后悔的。解释:
来自 C++/Java 背景的人们特别容易滥用/误用这个“特性”。但是,
__private
名称不像在 Java 或 C++ 中那样工作。它们只触发名称混淆,其目的是防止子类中的意外命名空间冲突:MyClass.__private
只变成了MyClass._MyClass__private
。(请注意,即使对于具有与超类相同名称的子类,例如不同模块中的子类,这也会失败。) 可以从其类的外部访问__private
名称,只是不方便和脆弱(它增加了对超类确切名称的依赖)。问题在于,类的作者可能会合理地认为“这个属性/方法名称应该是私有的,只能从此类定义内部访问”,并使用
__private
约定。但是,稍后,该类的用户可能会创建一个合法需要访问该名称的子类。因此,要么必须修改超类(可能很困难或不可能),要么子类代码必须使用手动混淆的名称(最多是丑陋和脆弱)。Python 中有一个概念:“我们都是同意的成年人”。如果您使用
__private
格式,那么您正在保护该属性免受谁的侵害?子类负责正确地使用超类的属性,超类负责正确地记录其属性。最好使用单个前导下划线约定,
_internal
。“这根本没有名称混淆;它只是向其他人指示“小心使用这个,它是内部实现细节;如果您不完全了解它,请勿触摸它”。但这只是一个约定。
单个前导下划线仅仅是一种惯例,意思是“你可能不应该使用它”。它并不能阻止其他人使用该属性。
双个前导下划线实际上会更改属性名称,这样继承层次结构中的两个类可以使用相同的属性名称,而不会发生冲突。
Python 中不存在访问控制。你可以访问类的所有属性,包括变量名被改名后的私有变量(例如 _class__variable
)。集中精力编写自己的代码和 API,而不是试图保护开发者免受自身影响。