下划线的分类解释

参考:https://blog.csdn.net/tcx1992/article/details/80105645

 

前面放一个下划线:_var

后面放一个下划线:var_

前面放二个下划线:__var

前面和后面各放二个下划线:__var__

单下划线:_

 

1、在变量名或方法名的前面放置单个下划线  【提示变量或方法仅供内部使用】

只是对程序员的一个提示:意味着Python社区一致认为它应该是什么意思,但程序的行为不受影响。

下划线前缀的含义是告知其他程序员:以单个下划线开头的变量或方法仅供内部使用。该约定在PEP 8中有定义。

这不是Python强制要求的写法,是程序员们自己造出来的方式,方便理解而已。

class Test:
    def __init__(self):
        self.foo = 11
        self._bar = 23


t = Test()
print(t.foo)
print(t._bar)  # 如果是在Pycharm中,会提示_bar是一个保护变量,但其实并不影响我们的访问

结果:

11

23

 

注意:

如果使用通配符(*)从模块中导入所有名称,则Python不会导入带有前导下划线的名称(除非模块定义了覆盖此行为的__all__列表)

from module import *

_inner()                # 错误

与通配符导入不同,常规导入不受前导单个下划线命名约定的影响。

import module

module._inner()   # 正确

 

2、末尾放置单个下划线  【避免关键字冲突】

有时候,一个变量的最合适的名称已经被一个关键字所占用。 因此,像class或def这样的名称不能用作Python中的变量名称。 在这种情况下,你可以附加一个下划线来解决命名冲突。

def make_object(name, class):
SyntaxError: "invalid syntax"

def make_object(name, class_):
...    pass

总之,单个末尾下划线(后缀)是一个约定,用来避免与Python关键字产生命名冲突。 PEP 8解释了这个约定。

 

3、前面放置二个下划线  【避免命名冲突】

双下划线前缀会导致Python解释器重写属性名称,以避免子类中的命名冲突。

这也叫做名称修饰(name mangling) - 解释器更改变量的名称,以便在类被扩展的时候不容易产生冲突。

class Test:
   def __init__(self):
       self.foo = 11
       self._bar = 23
       self.__baz = 23

a = Test()
print(a.__dict__)

打印结果:

{'foo': 11, '_bar': 23, '_Test__baz': 23}

如果你仔细观察,你会看到此对象上有一个名为_Test__baz的属性。 这就是Python解释器所做的名称修饰。 它这样做是为了防止变量在子类中被重写

 

编写一个子类来继承Test类。

class Test:
    def __init__(self):
        self.foo = 11
        self._bar = 23
        self.__baz = 23


class ExtendedTest(Test):
    def __init__(self):
        super().__init__()
        self.foo = 'overridden'
        self._bar = 'overridden'
        self.__baz = 'overridden'


t2 = ExtendedTest()
print(t2.foo)
'overridden'
print(t2._bar)
'overridden'
print(t2.__baz)   # 会报错

打印t2中的属性:

{'foo': 'overridden', '_bar': 'overridden', '_Test__baz': 23, '_ExtendedTest__baz': 'overridden'}

发现两个__baz属性通过类名区分开了。

_Test__baz

_ExtendedTest__baz

这就是双下划线的作用,防止覆盖。

 

双下划线名称修饰对程序员是完全透明的。也就是说,你无法通过类名.__baz来访问该变量,需要在类中定义其他的方法,来返回__baz的值。

 

名称修饰会影响在一个类的上下文中,以两个下划线字符("dunders")开头的所有名称

Python解释器自动将名称__mangled扩展为_MangledGlobal__mangled因为它以两个下划线字符开头

这表明名称修饰不是专门与类属性关联的。它适用于在类上下文中使用的两个下划线字符开头的任何名称。

_MangledGlobal__mangled = 23
 
class MangledGlobal:
   def test(self):
       return __mangled
 
MangledGlobal().test()
23

 

4、前面和后面都有二个下划线 【python特殊用途】

前后带有双下划线的变量或方法,是作为特殊用途使用的。

__init__,对象构造函数,或__call__ ,它使得一个对象可以被调用。

最好避免在自己的程序中使用以双下划线(“dunders”)开头和结尾的名称,以避免与将来Python语言的变化产生冲突。

也就是说,尽量不要在你的程序中使用前后双下划线,如果以后官方改了,你也得跟着改,没法很好的适配

 

5、单下划线 【临时变量 + 存储上一次的值】

按照习惯,有时候单个独立下划线是用作一个名字,来表示某个变量是临时的或无关紧要的。

在下面的循环中,我们不需要访问正在运行的索引,我们可以使用“_”来表示它只是一个临时值。

for _ in range(32):
...    print('Hello, World.')

同样,这个含义只是“依照约定”,并不会在Python解释器中触发特殊的行为。 单个下划线仅仅是一个有效的变量名称,会有这个用途而已。

 

你也可以在拆分(unpacking)表达式中将单个下划线用作“不关心的”变量,以忽略特定的值。

car = ('red', 'auto', 12, 3812.4)
color, _, _, mileage = car
 
color
'red'

mileage 3812.4
_ 12

 

'_' 还可以表示最近一个表达式的结果,好比Linux中的-表示上次访问的目录。

20 + 3
23
>>> _
23
>>> print(_)
23

 

总结:

posted @ 2019-11-06 16:38  道霖  阅读(1101)  评论(0)    收藏  举报