单一的意义是什么?
我想彻底澄清这一点。 有人可以解释在Python中的对象名前面加下划线的确切含义吗? 同时解释单个和双重前导下划线之间的区别。 另外,无论所讨论的对象是变量,函数还是方法等,这个意义是否保持不变?
单下划线
带有前导下划线的类中的名称仅用于向其他程序员指示该属性或方法是私有的。 然而,这个名字本身并没有什么特别之处。
引用PEP-8:
_single_leading_underscore:弱的“内部使用”指标。 例如, from M import *
不会导入名称以下划线开头的对象。
双下划线(Name Mangling)
从Python文档:
任何__spam
形式的__spam
(至少两个前导下划线,最多一个尾部下划线)在文本上用_classname__spam
替换,其中classname
是当前类名称,前导下划线被去除。 这种修改不考虑标识符的语法位置,所以它可以用来定义类 - 私有实例和类变量,方法,存储在全局变量中的变量,甚至是存储在实例中的变量。 这个类在其他类的实例上是私有的。
并在同一页面发出警告:
Name mangling旨在为类提供一种简单的方法来定义“私有”实例变量和方法,而无需担心由派生类定义的实例变量,或者通过类之外的代码使用实例变量。 请注意,强化规则的设计主要是为了避免事故; 确定的灵魂仍然可以访问或修改被认为是私人的变量。
例
>>> 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!'}
到目前为止已经有了很好的答案,但是一些消息不见了 一个前导下划线并不仅仅是一个约定:如果您使用from foobar import *
,并且模块foobar
没有定义__all__
列表,则从模块导入的名称不包含带有前导下划线的名称。 让我们说这主要是一个惯例,因为这个案例是一个相当晦涩的角落;-)。
前导 - 下划线约定不仅用于私有名称,而且还用于C ++称为受保护属性的约定 - 例如,完全打算被子类覆盖的方法名称(甚至是那些必须被覆盖的属性它们raise NotImplementedError
的基类raise NotImplementedError
! - )通常是单raise NotImplementedError
下划线名称,用于指示使用该类(或子类)的实例进行编码, 以避免所述方法直接被调用。
例如,为了创建一个线程安全的队列,其队列规则与FIFO不同,需要导入Queue,Queue.Queue的子类,并覆盖_get
和_put
等方法; “客户端代码”从来不会调用这些(“钩子”)方法,而是(“组织化”)公共方法,比如put
和get
(这就是所谓的模板方法设计模式 - 参见例如一个有趣的演示文稿,基于一个关于这个问题的演讲视频,以及附加的成绩单概要)。
__foo__
:这只是一个约定,是Python系统使用不会与用户名发生冲突的名称的一种方式。
_foo
:这只是一种约定,是程序员指出变量是私有的方式(无论在Python中如何)。
__foo
:这具有真正的含义:解释器用_classname__foo
替换这个名称,以确保该名称不会与另一个类中的类似名称重叠。
Python世界中没有其他形式的下划线有意义。
这些约定中的类,变量,全局等没有区别。
链接地址: http://www.djcxy.com/p/30471.html