单下划线和双下划线在对象名称之前的含义是什么?

2024-03-28 22:47:41 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

单下划线

在类中,带有前导下划线的名称只是为了向其他程序员表明属性或方法是私有的。不过,名字本身并没有什么特别之处。

引用PEP-8

_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

双下划线(名称损坏)

来自the Python docs

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances. private to this class on instances of other classes.

以及同一页的警告:

Name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class. Note that the mangling rules are designed mostly to avoid accidents; it still is possible for a determined soul to access or modify a variable that is considered private.

示例

>>> 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__列表,则从模块导入的名称不包括带有前导下划线的名称。假设它主要是一个惯例,因为这个例子是一个非常模糊的角落;-)。

主要的下划线约定不仅广泛用于私有EME>名称,而且还用于C++所称的受保护的类——例如,完全被类(甚至是<强> ><>强>的方法的名称,在基类中被重写,因为它们{{CD4}}!-)通常是一个前导下划线名称,用该类(或子类)的实例来指示代码,该类(或子类)不打算直接调用所述方法。

例如,要使线程安全的队列具有不同于FIFO的排队规则,可以导入queue、子类queue.queue并重写诸如_get_put;“客户机代码”从不调用那些(“hook”)方法,而是调用诸如putget(这称为Template Method设计)的公共方法模式——请参见here,这是一个有趣的演示,它基于我关于这个主题的一段谈话的视频,并添加了转录本的摘要)。

编辑:谈话内容中的视频链接现已断开。您可以找到前两个视频herehere

__foo__:这只是一个约定,是Python系统使用不与用户名冲突的名称的一种方式。

_foo:这只是一种约定,程序员可以通过这种方式指示变量是私有的(无论在Python中是什么意思)。

__foo:这有真正的意义:解释器用_classname__foo替换这个名称,以确保该名称不会与另一个类中的类似名称重叠。

在Python世界中,没有其他形式的下划线有意义。

在这些约定中,类、变量、全局等没有区别。

相关问题 更多 >