本文译自:https://shahriar.svbtle.com/underscores-in-python
本文讨论了Python中_字符的使用。就像Python里的很多东西一样,我们会看到,_不同的用法(不总是!)是一个惯例问题。
一:单独的单下划线(_):
通常在3中情形中使用:
1:在解释器中: _指向交互式解释器会话中最后一个执行语句的结果。这首先是由标准的CPython解释器完成的,其他人也跟着做了。
> _
Traceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name '_' is not defined
> 42
> _
42
> 'alright!' if _ else ':('
'alright!'
> _
'alright!':
2:作为变量名称:
这与前一点有一定的关系。_用作一次性的名字,_将让下一个阅读您代码的人知道,按照约定,一个变量被指定了名称,但不打算使用。例如,您可能对循环计数器变量的实际值不感兴趣:
n = 42
for _ in range(n):
do_something()
3:i18n:还可以看到_被用作函数名。
在这种情况下,通常用于实现国际化和本地化字符串转换查找的函数的名称。这似乎起源并遵循相应的C约定。
例如,正如在Django用于翻译的文档,您可能有:
from django.utils.translation import ugettext as _
from django.http import HttpResponse
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)
第二和第三点可能会发生冲突,因此应该避免在任何使用_进行i18n查找和翻译de 代码块中,使用_作为一次性的名称。
二:在名称前面使用单下划线(例如,_shahriar)
_name由程序员用于指定为“私有”的名称。这是一种惯例,将使使用您的代码的下一个人(或您自己)知道以_开头的名称是内部使用的。正如Python文档注释:
a name prefixed with an underscore (e.g. _spam
) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.
我说是一种惯例,是因为它确实对interpretor有意义;如果您 from <module/package> import *
,那么以_开始的名称都不会导入,除非模块的__all__列表显式地包含它们。请参阅“Importing *
in Python” 以获得更多信息。
三:在名字前面加双下划线(例如,__shahriar)
在名称(特别是方法名)前使用双下划线(__)并不是惯例;它对Interpreter有特殊的意义。Python将这些名称进行管理,并用它来避免f父类名称与子类定义的名称冲突。正如Python文档所指出的那样,任何__spam(至少有两个前置_,最多一个后置下划线)的标识符都被替换为_classname__spam,其中classname是当前的类名,其前面的下划线被删除了。
下面的例子:
class A(object):
def _internal_use(self):
pass
def __method_name(self):
pass
dir(A())
['_A__method_name', ..., '_internal_use']
如预期的那样,_internal_use没有更改,但__method_namE变为_ClassName__method_name。现在,如果您创建a的子类,比方说B(argh,bad,badname!),那么您就不能轻松地覆盖a的__method_name:
class B(A):
def __method_name(self):
pass
dir(B())
['_A__method_name', '_B__method_name', ..., '_internal_use']
这里的预期行为几乎等同java 中的final method和C++中的普通(非虚)方法。
四:在名称之前和之后的双重下划线(例如__init__)
这些是Python使用的特殊方法名称。就个人而言,这只是一个约定,是Python系统使用不与用户定义的名称冲突的名称的一种方式。然后,您通常会重写这些方法,并在Python调用它们时定义所需的行为。例如,在编写类时,通常会重写__init__方法。
没有什么可以阻止你写你自己的特别方法的名字(但是,请不要这样做):
>>> class C(object):
... def __mine__(self):
... pass
...
>>> dir(C)
... [..., '__mine__', ...]
请只让python定义的特殊名称遵循这个约定!!!