下划线的五种含义
单前导下划线:_var
变量和方法名称的单个下划线前缀有约定俗称的含义,表示Python社区一致认为它应该是什么含义但是程序的行为不受影响。该含义是告诉其他程序员:单个下划线开头的变量与方法名称仅供内部使用
但是对于从模块中导入名称的方式是会有影响的。当使用通配符*
导入所有名称的时,Python不会导入带有前导下划线的名称。
#变量或方法名称命名
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
t = Test()
t._bar # 23
#模块中的
# my_module.py
def external_func():
return 23
def _internal_func():
return 42
#使用通配符导入
from my_module import *
_internal_func()#NameError: "name '_internal_func' is not defined"
#正常导入
import my_module
my_module._internal_func()#42
单末尾下划线 var_
在一个变量最合适的名称已经被一个关键字所占用的时候,可以在其之后附加一个下划线来解决命名冲突。这是一个约定,PEP8 解释了这个约定
双前导下划线 __var
双下划线的前缀会导致Python解释器重写属性名称,以避免子类的命名冲突,这也叫做名称修饰
——解释器更改变量的名称,以变类在扩展的时候不容易产生冲突。
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
self.__baz = 23
t = Test()
#内置dir()函数查看对象的属性
dir(t)
['_Test__baz', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', '_bar', 'foo']
可以看到在属性列表里面是没有__baz
属性,但是有一个_Test__baz
这就是Python解释器所作的名称修饰,这样做是为了防止变量在子类中被重写。
#继承了Test类
class ExtendedTest(Test):
def __init__(self):
super().__init__()
self.foo = 'overridden'
self._bar = 'overridden'
self.__baz = 'overridden'
t2 = ExtendedTest()
dir(t2)
['_ExtendedTest__baz', '_Test__baz', '__class__', '__delattr__',
'__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__le__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '_bar', 'foo', 'get_vars']
可以看到__baz
这个属性在父类和子类中都出现了,但是使用实例调用此属性的话会提示'ExtendedTest' object has no attribute '__baz'
,原因就是已经被给改过名字了。
关于调用可以使用被重命名过的属性名,也就是_classname
做前缀,也可以在类内使用函数进行调用返回。
若是你使用了命名了全局变量,命名方式使用的是该名称修饰规则,并且把名字重了,这样的话类中没有这个属性,但是调用会直接使用这个全局变量
_MangledGlobal__mangled = 23
class MangledGlobal:
def test(self):
return __mangled
#MangledGlobal()即是完成了实例化
#但是输出
MangledGlobal().test()# 23
双前导和双末尾下划线 __var__
Python保留了对双前导和双下划线的名称用于特殊用途。这种方法被称为魔术方法
。详细的手册可以看Python魔术方法指南。所以最好避免在自己的程序中使用双下划线
的开头和结尾的名称,避免与Python语言的变化产生冲突。
单下划线 _
第一个作用:
按照习惯,有时单个独立下划线是最为一个名字的,表示某个变量是临时的或者无关紧要的。这个含义只是”按照约定”,并不会在Python中出发特殊行为。单个下划线仅仅是一个有效的变量名称。
第二个作用:
除了作为临时变量之外,_
是大多数Python RERL中的一个特殊变量,它表示由编译器评估的最近一个表达式的结果
1+2 #3
_ # 3
list() # []
_.append(1)
_ # [1]
本片是对知乎的这篇文章的学习与实验写出来的