在 Python 中,函数或变量名前面加单下划线 _
或双下划线 __
是一种命名约定,用来表达特定的含义或功能,主要与 作用域、可见性 和 命名冲突 有关。以下是具体的解释:
1. 单下划线 _
变量或函数名以 _
开头
当变量或函数名前加一个下划线 _
,它是一种非强制性的约定,表示这是一个 “内部使用的”对象,不建议在模块或类的外部直接访问(即 受保护的访问)。
作用:提示其他开发者,这是一个内部使用的成员,不应该随意访问,但实际上它是可以访问的。
示例:
class MyClass:
def __init__(self):
self._internal_var = 42 # 约定这个变量是内部使用的
def _internal_method(self): # 内部方法
print("This is an internal method")
# 外部访问示例
obj = MyClass()
print(obj._internal_var) # 可以访问,但不推荐
obj._internal_method() # 可以调用,但这违背了约定
注意:
单下划线只是约定,并不会真正限制访问。它更像是一种“友情提醒”。
在交互式环境中的 _
特殊用法
在 Python 的交互式解释器中,单个下划线 _
通常表示 最后一次执行结果。
>>> 10 + 20
30
>>> _ * 2 # 使用前一个结果
60
2. 双下划线 __
变量或方法名以 __
开头
当变量或方法名前加 双下划线 __
,它会触发 Python 的 名称重整机制(Name Mangling),用来避免子类覆盖父类中的同名属性或方法,或者避免意外修改。
作用:将变量名重整为 _类名__变量名
的形式,以实现 名称混淆,在类的外部无法直接访问。
示例:
class MyClass:
def __init__(self):
self.__private_var = 100 # 触发名称重整
def __private_method(self): # 触发名称重整
print("This is a private method")
# 外部访问示例
obj = MyClass()
# 直接访问会报错
# print(obj.__private_var) # AttributeError: 'MyClass' object has no attribute '__private_var'
# obj.__private_method() # AttributeError: 'MyClass' object has no attribute '__private_method'
# 但可以通过“名称重整”的结果访问(不推荐)
print(obj._MyClass__private_var) # 100
obj._MyClass__private_method() # This is a private method
注意:
- 双下划线开头的变量和方法仍然可以通过特殊的
_类名__变量名
形式访问。 - 设计初衷 是为了防止子类意外覆盖父类的方法或属性,但不是真的让这些变量变成完全“私有”。
魔术方法 / 双下划线开头和结尾
如果一个方法或变量名以 双下划线开头和结尾,比如 __init__
或 __str__
,它通常是 Python 预定义的特殊方法或属性,用于实现某些功能(即“魔术方法”)。
这些方法是 Python 内部的一部分,通常不需要手动调用,系统会自动调用。
示例:
__init__
: 用于初始化对象。__str__
: 定义对象的字符串表示。__len__
: 定义对象的长度。__getitem__
: 定义对象的索引访问方式。
class MyClass:
def __init__(self, name):
self.name = name
def __str__(self):
return f"MyClass object with name: {self.name}"
obj = MyClass("example")
print(obj) # 自动调用 __str__: 输出 "MyClass object with name: example"
注意:
不要随意定义名字以双下划线开头和结尾的方法或变量,除非你确实想覆盖 Python 的内置功能。
3. 单下划线 _
作为变量名
单下划线作为临时变量
在 Python 中,单下划线 _
经常用于表示临时变量,或表示不关心的变量(即变量值会被忽略)。
示例:
# 解包时忽略某些值
a, _, c = (1, 2, 3)
print(a, c) # 输出: 1 3
# 遍历时不关心循环变量
for _ in range(5):
print("Hello") # 输出 5 次 Hello
总结:不同下划线的含义
符号 | 用途 |
---|---|
_name | 受保护的约定:表示“内部使用”的变量或方法,但不是真正的私有(外部仍然可以访问)。 |
__name | 名称重整机制:避免子类覆盖或外部直接访问,通过 _类名__变量名 的形式 |