Python中的单下划线与双下划线含义和一些特殊约定
Python中的单下划线和双下划线在变量名和方法名中有一些特殊的约定和含义,在这尽力解释清楚。
常见的五种形式:
前置单下划线: _var
后置单下划线: var_
前置双下划线:__var
前后双下划线:__var__
单下划线:_
1、前置单下划线
在涉及变量名和方法名时,前置单下划线并无特殊含义,只是程序员之间的约定,表示这个变量或方法只供内部使用,不充当公共接口。(Python代码风格指南 PEP8 定义了这个约定)。因为只是人为约定,所以Python解释器是不识别这个的。如下所示:
虽然在涉及变量名和方法名时是一个公认的约定,但前置下划线会影响到从模块中导入名称的方式,例如:
# my_module.py:
def external_func():
return 23
def _internal_func():
return 42
如果使用通配符导入这个模块的所有名称,Python不会导入带有前置单下划线的名称(除非模块中定义了 __all__列表覆盖了这个行为)。
使用常规导入就不受前置单下划线的影响。
2、后置单下划线
有时想用的变量名如果与Python关键字冲突,可以在其后加上单下划线来避免冲突。这也是一个约定。
3、前置双下划线
前置双下划线在Python有特殊的含义,它会让Python重写属性名称,以避免与子类中的命名冲突。又叫做名称改写( name mangling )。
dir 函数返回一个包含对象属性的列表,可以看到,该列表中有 foo,_bar,但是没有 __baz。实际上,__baz已经被自动重写为 _Test__baz 了,这是为了防止子类覆盖这些变量。
试验一下,创建一个类来扩展 Test类,并尝试覆盖之前的属性。
可以看到,foo,_bar都被成功覆盖掉了,但是带双下划线的 __baz 是覆盖不了的,因为它的名称已经改写了,访问不到!
子类的 __baz 已经变成了 _ExtendTest__baz,原来的 _Test__baz 还在。
名称改写也同样适用于方法名,会影响所有在类环境中的以双下划线开头的名称。
总之,名称改写能够应用于所有类环境中的带前置双下划线的名称。
4、前后双下划线
如果名字前后都有前置双下划线,就不会引起改写,带前后双下划线的名称在Python中有特殊的用途。像 __init__这样的对象构造函数,用来让对象可调用的 __call__ 函数等。
如果熟练的话,可以根据需要来自己定义这些函数,以实现一些特殊的效果。
5、单下划线
单下划线通常是用来做临时的、无关紧要的变量。
for _ in range(10):
print("hello world")
这只是个约定,也可以用其他的变量。
另外,在大多数 Python REPL 中 单下划线 _ 是一个特殊变量,表示由解释器计算的上一个表达式的结果。如下:
总结:
前置单下划线 _var:命名约定,表示只在内部使用,对Python解释器没有特殊含义。
后置单下划线 var_:命名约定,避免与关键字冲突。
前置双下划线 __var:在类环境中会触发名称改写,对Python解释器有特殊含义。
前后双下划线 __var__:表示由Python语言定义的特殊方法。
单下划线 _ :有时用作临时或无意义的变量,还在 Python REPL中充当上一个表达式的结果。
想详细了解的可以看一下原书
reference:
《深入理解Python特性》Dan Bader
上一篇: Python2.X输入函数