【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
有人可以解释一下在Python中对象名称前加下划线的确切含义吗? 另外,请说明单首和双首下划线之间的区别。 此外,无论所讨论的对象是变量,函数,方法等,该含义是否都保持不变?
#1楼
._variable
是._variable
的,仅用于约定
.__variable
通常被错误地认为是超私有的,而其实际含义只是为了防止意外访问而使用 namemangle [1]
.__variable__
通常保留给内置方法或变量
如果您非常需要,仍可以访问.__mangled
变量。 双下划线仅将变量命名或将变量重命名为instance._className__mangled
例:
class Test(object):
def __init__(self):
self.__a = 'a'
self._b = 'b'
>>> t = Test()
>>> t._b
'b'
t._b是可访问的,因为它仅被约定隐藏
>>> t.__a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'
找不到t .__ a,因为由于名称修改而不再存在
>>> t._Test__a
'a'
通过访问instance._className__variable
而不是双下划线名称,您可以访问隐藏值
#2楼
单下划线
类中带有下划线的名称仅是为了向其他程序员表明该属性或方法旨在私有。 但是,名称本身并没有做任何特别的事情。
引用PEP-8 :
_single_leading_underscore:“内部使用”指标较弱。 例如,
from M import *
不会导入名称以下划线开头的对象。
双下划线(名称改写)
从Python文档 :
形式为
__spam
任何标识符(至少两个前导下划线,至多一个下划线)在文本上被_classname__spam
替换,其中classname
是当前的类名,其中前导下划线被去除。 进行这种修饰时无需考虑标识符的语法位置,因此可以用于定义类私有实例和类变量,方法,全局变量中存储的变量,甚至实例中存储的变量。 在其他类的实例上对此类私有。
和来自同一页面的警告:
名称修饰旨在为类提供一种轻松的方法,以定义“私有”实例变量和方法,而不必担心派生类定义的实例变量或类外部代码对实例变量的处理。 请注意,修改规则主要是为了避免发生意外。 坚定的灵魂仍然有可能访问或修改被视为私有的变量。
例
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
#3楼
单个下划线是惯例。 名称是否以单个下划线开头,与解释器的观点没有区别。
内置方法使用双__bool__
和尾部下划线,例如__init__
, __init__
__bool__
等。
双下划线开头W / O尾随同行是惯例也是如此,但是,该类方法将被错位的解释。 对于变量或基本函数名称,没有区别。
#4楼
__foo__
:这只是一个约定,是Python系统使用不会与用户名冲突的名称的一种方式。
_foo
:这只是一个约定,程序员可以通过这种方式表明该变量是私有的(无论在Python中是什么意思)。
__foo
:这是真实的含义:解释器用_classname__foo
替换此名称,以确保该名称不会与另一个类中的相似名称重叠。
在Python世界中,没有其他形式的下划线具有意义。
在这些约定中,类,变量,全局等之间没有区别。
#5楼
您的问题很好,这不仅与方法有关。 模块中的函数和对象通常也以一个下划线为前缀,并且可以以两个为前缀。
但是,例如,__double_underscore名称在模块中没有名称混杂。 发生的情况是,如果您从模块(从module import *)全部导入,则不会导入以一个(或多个)下划线开头的名称,也不会在help(module)中显示名称。
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3141434