Python前后带下划线的属性有什么区别
我想知道在Python中,这些有什么区别?
self._var1
self._var1_
self.__var1
self.__var1__
1 个回答
作为一个入门指南,你可能会觉得下面这段来自PEP 8 - Python 代码风格指南的引用很有帮助:
此外,以下使用前导或后缀下划线的特殊形式被认可(这些通常可以与任何命名规则结合使用):
_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__
。切勿自己发明这样的名称;只使用文档中已有的名称。
不过你提到的是类属性,所以我们来看看你的具体例子:
单前导下划线
在你的类中命名一个属性为 self._var1
,这表示这个属性应该只被类内部(或者可能是子类)访问,用户不需要直接访问它,也不应该修改它。你应该在使用 private
或 protected
字段的地方使用前导下划线,但要知道,Python 并不会强制限制访问——你需要信任使用你类的用户不会做傻事,并且如果他们真的很确定自己知道自己在做什么,并且这样做是合理的,他们可以选择访问(或修改)你的类的私有字段。
单前导和后缀下划线
self._var1_
是我从未见过的。我认为这种命名风格在 Python 世界中没有任何约定的含义。
双前导下划线
这个命名方式实际上有语法上的意义。在你的类内部引用 self.__var1
会触发名称改名。在类外部,这个变量会显示为 self._YourClassName__var1
而不是 self.__var1
。并不是每个人都会使用这个命名方式——我所在的地方就完全不使用——对于简单的类来说,这感觉像是比使用单前导下划线更荒谬和烦人的选择。
不过,这种命名方式存在是有理由的;如果你使用了很多继承,单前导下划线就无法向阅读你代码的人表明“私有”和“受保护”变量之间的区别——有些变量甚至不应该被子类访问,而有些变量子类可以访问,但外部世界不可以。因此,在这种情况下,使用单前导下划线表示“受保护”,而双下划线表示“私有”可能是一个有用的约定(而且名称改名会允许子类使用同名变量而不会造成冲突)。
双前导和后缀下划线
self.__var1__
是你绝对不应该创建的,因为双前导和后缀下划线的命名风格仅用于 Python 定义的具有特殊含义的名称,比如 __init__
或 __eq__
方法。你可以重写这些方法来改变类的行为(实际上,几乎所有类都会有程序员定义的 __init__
),但你不应该像 self.__var1__
这样自己发明名称。