python中的下划线"_"讲解
python中,下划线 不管是单独作为变量名或者作为变量名的前缀或者后缀,是有特殊含义的,下面简要的来总结一下。
1, 单下划线
在python3中,单下划线 默认为空字符串变量,如下图:
一旦交互式解释器会话中上一条语句执行的结果没有通过赋值语句赋值给一个变量,则该值默认赋值给 ,如下图所示:
单下划线 也可以作为临时变量来使用,例如,下面的例子中,你可能对循环计数中的实际值并不感兴趣,此时就可以使用 。
n = 42
for _ in range(n):
do_something()
2,作为变量前的单下划线 ,如_xxx
python中单下划线开头的变量,标明是一个受保护(protected)的变量,原则上不允许直接访问,但外部类还是可以访问到这个变量的。
这只是程序员之间的一个约定,用于警告说明这是一个私有变量,外部类不要去访问它。
如下所示,在Student类中定义了一个受保护变量_name,外部是可以访问到这个变量的,但是不推荐这样干。
class Student:
def __init__(self, name, age):
self._name = name
self.age=age
stu = Student('hello',30)
print(stu.age) #30
print(stu._name) #hello
另外在以开头的名称都不会被 这种形式导入,这种情况也适用于__xxx, __xxx__,如下所示,简单的在模块test1中定义4个模块变量,然后在模块test2中以from test1 import *形式导入。
模块test1.py:
'''模块test1.py'''
'''定义4个模块变量'''
num = 20
_num = 90
__num = 900
__num__ = 10
模块test2.py:
'''模块test2.py'''
from test1 import *
print(num) #输出20
print(_num) #报错,name '_num' is not defined
print(__num) #报错,name '__num' is not defined
print(__num__) #报错,name '__num__' is not defined
如果是import test1的形式导入是没问题的:
模块test2.py:
'''模块test2.py'''
import test1
print(test1.num) #输出20
print(test1._num) #输出90
print(test1.__num) #输出900
print(test1.__num__) #输出10
3,作为变量前的双下划线 ,如__xxx
在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,因为Python解释器对外把 __xxx变量改成了_classname__xxx,所以,仍然可以通过_classname__xxx来访问__xxx变量:所以,我们把test1.py中的Student类改一改:
class Student:
def __init__(self, name, age):
self.__name = name
self.age=age
stu = Student('hello',30)
print(stu.age) #输出30
print(stu.__name) #报错:AttributeError: 'Student' object has no attribute '__name'
print(stu._Student__name) #输出hello
4,变量前后的双下划线 如__xxx__
这种用法表示Python中特殊的方法名。其实,这只是一种惯例,对Python系统来说,这将确保不会与用户自定义的名称冲突。通常,你将会 覆写这些方法,并在里面实现你所需要的功能,以便Python调用它们。例如,当定义一个类时,你经常会覆写“__init__”方法。
双下划线开头双下划线结尾的是一些 Python 的“魔术”对象,如类成员的 __init__、__del__、__add__、__getitem__ 等,以及全局的 __file__、__name__ 等。 Python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数,而是按照文档说明来使用。 虽然你也可以编写自己的特殊方法名,但不要这样做。
5,题外话 if __name__ == “__main__”:
经常在一些python程序中看见这样的写法。
因为所有的 Python 模块都是对象并且有几个有用的属性,你可以使用这些属性方便利的测试你所书写的模块。
模块是对象, 并且所有的模块都有一个内置属性 __name__。一个模块的 __name__ 的值要看您如何应用模块。如果 import 模块, 那么__name__的值通常为模块的文件名, 不带路径或者文件扩展名。但是您也可以像一个标准的程序一样直接运行模块, 在这种情况下__name__的值将是一个特别的缺省值:__main__。
6,总结:
需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__age__这样的变量名。
有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__xxx是因为Python解释器对外把__xxx变量改成了_classname__xxx,所以,仍然可以通过_classname__xxx来访问__xxx变量。
参考
- https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318650247930b1b21d7d3c64fe38c4b5a80d4469ad7000
- https://blog.csdn.net/youngbit007/article/details/61616241
- http://python.jobbole.com/81129/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
- https://www.cnblogs.com/MUMO/p/5718578.html