详解Python 下划线、双下划线的涵义

  • Post category:Python

在Python中,下划线(_)的使用非常多,它具备特殊的含义或用途。双下划线(__)也有类似的作用,但更为特殊。下面我将详细讲解它们的使用方法。

单下划线(_)的使用

作为单独的变量名

如果你使用_作为单独的变量名,在Python解释器中它将被解释为一个“临时变量”,用于保存上一次执行结果中的临时值。例如:

>>> x = 5
>>> y = 6
>>> x + y
11
>>> _
11
>>> print(_)
11

在上面的代码中,_保存了上一次执行结果中的值(即11),可以使用_来获取这个值。同样,_也可以被赋值为其他的值。

作为“不重要”的变量名

有时候,我们定义了一个函数或方法,但没有使用其中的某些参数。通常情况下,这会造成语法错误,因为有未使用的变量。此时,可以将未使用的变量名定义为_。这样做可以告诉读者该参数是不重要的,从而避免不必要的误解。例如:

def func(a, b, _):
    return a + b

作为“私有”的变量名

在Python中,没有真正的私有变量。但是,如果你将变量名定义为以单个下划线开头,这意味着该变量被视为“私有”的,应该避免直接访问。这只是一种命名习惯,没有实际的安全保障。例如:

class MyClass():
    def __init__(self):
        self._value = 42

在上面的代码中,_value被视为是“私有的”,应该避免直接访问。但实际上,你仍然可以从外部访问它。这只是一种约定俗成的命名方式。

双下划线(__)的使用

名称重整(Name Mangling)

在Python中,如果将变量或方法名定义为以双下划线开头,然后没有以双下划线结尾,将会发生名称重整(Name Mangling)。在重整过程中,Python会将变量或方法名转换为_[类名]__[变量名]_[类名]__[方法名]的形式。这种机制可以用于实现“保护”变量或方法的作用。例如:

class MyClass():
    def __init__(self):
        self.__value = 42

    def print_value(self):
        print(self.__value)

obj = MyClass()
obj.print_value()

在上面的代码中,__value被视为是“私有的”,无法从外部访问。但实际上,你仍然可以通过obj._MyClass__value来访问它。这种机制可以防止意外修改受保护的变量或方法。

虚拟子类(Virtual Subclasses)

在Python中,有一些特殊的内置类型(如intstr等),它们的行为受到一些特殊方法的影响。例如,整数类型可以使用__add__方法实现加法功能。但是,并不是所有类型都可以直接使用这些方法。如果一个类定义了这些方法,但不是这些内置类型的子类,那么这些方法就不会被调用。

为了解决这个问题,Python引入了虚拟子类(Virtual Subclasses)的概念。如果一个类定义了以双下划线开头和结尾的特殊方法,Python将自动将其注册为对应的虚拟子类。例如:

class MyInt():
    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        return MyInt(self.value + other.value)

class MyLongInt(MyInt):
    def __init__(self, value):
        super().__init__(value)

    def __int__(self):
        return self.value

class MyFloatingPoint():
    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        return MyFloatingPoint(self.value + other.value)

a = MyInt(1)
b = MyInt(2)
print(a + b)

c = MyLongInt(3)
d = MyLongInt(4)
print(c + d)

e = MyFloatingPoint(2.3)
f = MyFloatingPoint(3.4)
print(e + f)

在上面的代码中,我们定义了三个类MyIntMyLongIntMyFloatingPointMyInt定义了加法运算符__add__MyLongInt继承自MyIntMyFloatingPoint也定义了加法运算符__add__

但是,由于MyIntMyFloatingPoint并不是int类型和float类型的子类,因此这些方法不会被Python自动调用。为了解决这个问题,我们可以在这些方法的函数名前后加上双下划线,使它们成为虚拟子类。这样,Python将自动将MyIntMyFloatingPoint注册为int类型和float类型的虚拟子类,这些方法就会被正确地调用。

总结

下划线和双下划线在Python中具有特殊的含义和作用。单下划线可以用作临时变量、不重要的变量或私有变量;双下划线可以用作名称重整或虚拟子类的概念。只有理解了这些特殊的用途,才能更好地使用Python编程语言。