1. 单下划线用作变量

   最常见的一种使用场景是作为变量占位符,使用场景明显可以减少代码中多余变量的使用。为了方便理解,_可以看作被丢弃的变量名称,

   这样做可以让阅读你代码的人知道,这是个不会被使用的变量。

alist = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
for _, _, x in alist:
    print(x)   # 3, 6, 9

 

2. 单下划线前缀名称

   以下划线“_”为前缀的名称应该被视为API中非公开的部分(不管是函数、方法还是数据成员),指定该名称属性为“私有”,只能内部使用。

   1)类中定义下划线开头的属性或者方法。相当于 protected 限定的变量,表示外部无法访问,子类可以继承。虽然这么定义了,但 Python 并不

      会真的阻止别人访问内部名称,即如果外部想访问这个保护的变量也是可以的,所以只是一种约定。

   2)模块(.py文件)中定义下划线开头的变量或者函数。这么定义的话,通过 from module import * 或 import module 这两种方式便无法将下划

      线开头的变量或函数导入,但是可以通过 from module import _var 这种指定的方式导入。

 

3. 单下划线后缀名称 

   通常用于和 Python 关键词区分开来,比如我们需要一个变量叫做 var,但 var 是 Python 的关键词,就可以以单下划线结尾写作 var_。

 

4. 双下划线前缀名称

   Python文档指出,“__var”这种形式(至少两个前导下划线,最多一个后续下划线)的任何标识符将会被“_classname__spam”这种形式原文取代,

   在这里“classname”是去掉前导下划线的当前类名。直接看个例子:

class A(object):
    def __init__(self):
        self.__private = 0

    def _internal_use(self):
        pass

    def __method_name(self):
        pass

obj = A()
print(obj)  # ['_A__method_name', '_A__private', '_internal_use', ...]
print(obj._A__private)  # 正确
print(obj.__private)    # 'A' object has no attribute '__private'

   可以看到 __private 和 __method_name 都被重新命名为 _A__method_name 和 _A__private。

   可以看出因为双下划线开头的属性或者方法的名字被内部改掉了,于是外部访问的时候就会发生无定义的情况。

   不仅外部无法访问,这种属性通过继承也是无法被覆盖的。我们来定义一个继承自A的类B。

class B(A):
    def __init__(self):
        super().__init__()
        self.__private = 1   # Does not override A.__private

        # Does not override B.__private_method()
        def __private_method(self):
            pass

obj = B()
print(dir(obj))  # ['_A__method_name', '_A__private', '_B__private', '_internal_use', ...]

   这里,私有名称 __private 和 __private_method 被重命名为 _B__private 和_B__private_method ,这个跟父类 A 中的名称是完全不同的。

   由此可见,虽然 B 继承了 '_A__method_name' 和 '_A__private',但操作原先的变量名却不是访问,而是定义。所以双下划线变量就很类似于

   privated 限定的,外部和子类都无法直接访问。