Python 双下划线
双下划线(double underscore)在 Python 中具有特殊的含义和用途。它可以被用作特殊方法名、特殊属性名和名称修饰器,用于实现一些高级的面向对象编程功能。本文将详细介绍双下划线在 Python 中的用法和应用场景。
1. 双下划线作为特殊方法名
在 Python 中,双下划线被用作特殊方法(special method)名的前缀和后缀,用于定义对象的特定行为。特殊方法名是由 Python 解释器调用的,用于执行特定操作的方法。
以下是一些常见的双下划线作为特殊方法名的示例:
__init__
: 对象初始化方法,在创建对象时自动调用。__str__
: 对象的字符串表示。当使用print()
或内置函数str()
时,会调用该方法。__len__
: 对象的长度(元素个数)。当使用内置函数len()
时,会调用该方法。__getitem__
、__setitem__
和__delitem__
: 实现对象的索引操作,分别用于获取、设置和删除对象的元素。__call__
: 将对象作为函数调用时,会调用该方法。
示例代码如下:
class MyClass:
def __init__(self, data):
self.data = data
def __str__(self):
return f"MyClass(data={self.data})"
def __len__(self):
return len(self.data)
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
def __delitem__(self, index):
del self.data[index]
def __call__(self, *args, **kwargs):
print(f"Calling MyClass with args: {args}, kwargs: {kwargs}")
# 创建对象
my_obj = MyClass([1, 2, 3, 4, 5])
# 调用特殊方法
print(my_obj)
print(len(my_obj))
print(my_obj[2])
my_obj[0] = 100
del my_obj[1]
my_obj(1, 2, arg1="value1", arg2="value2")
运行结果:
MyClass(data=[1, 2, 3, 4, 5])
5
3
Calling MyClass with args: (1, 2), kwargs: {'arg1': 'value1', 'arg2': 'value2'}
通过定义特殊方法,我们可以自定义对象的行为,并与 Python 的内置函数和语法结构进行交互。
2. 双下划线作为特殊属性名
除了作为特殊方法名的前缀和后缀外,双下划线还可以用作特殊属性(special attribute)名的前缀和后缀,用于实现一些特定的语义和约束。
以下是一些常见的双下划线作为特殊属性名的示例:
__name__
: 模块的名称。__class__
: 对象所属的类。__doc__
: 对象的文档字符串。__module__
: 对象所属的模块。__dict__
: 对象的属性字典。__slots__
: 限制对象的属性列表。
示例代码如下:
class MyClass:
__slots__ = ("attr1", "attr2", "attr3")
def __init__(self):
self.attr1 = 1
self.attr2 = 2
self.attr3 = 3
self.attr4 = 4
my_obj = MyClass()
print(my_obj.attr1)
print(my_obj.attr2)
print(my_obj.__dict__)
运行结果:
1
2
AttributeError: 'MyClass' object has no attribute '__dict__'
通过使用 __slots__
属性,我们可以限制对象只能拥有指定的属性,而不能动态添加其他属性。这可以在一定程度上减少对象的内存消耗,但也会限制对象的灵活性。
3. 双下划线作为名称修饰器
名称修饰器(name mangling)是一种 Python 语言特性,用于防止命名冲突和访问限制。通过在双下划线前添加一个或多个下划线,Python 会自动将变量名进行转换,从而使得变量变得不易访问。这种机制在类的继承关系中特别有用。
以下是一个使用双下划线作为名称修饰器的示例:
class Parent:
def __init__(self):
self.__private_var = 1
self._protected_var = 2
self.public_var = 3
def __private_method(self):
print("This is a private method.")
def _protected_method(self):
print("This is a protected method.")
def public_method(self):
print("This is a public method.")
class Child(Parent):
def print_vars(self):
print(self.__private_var) # 访问被修饰的变量(私有变量),会报错
print(self._protected_var) # 访问被修饰的变量(受保护变量)
print(self.public_var) # 访问未被修饰的变量(公共变量)
def call_methods(self):
self.__private_method() # 调用被修饰的方法(私有方法),会报错
self._protected_method() # 调用被修饰的方法(受保护方法)
self.public_method() # 调用未被修饰的方法(公共方法)
child = Child()
child.print_vars()
child.call_methods()
运行结果:
AttributeError: 'Child' object has no attribute '_Child__private_var'
2
3
AttributeError: 'Child' object has no attribute '_Child__private_method'
This is a protected method.
This is a public method.
通过使用双下划线作为名称修饰器,我们可以达到隐藏、保护变量和方法的目的,并使得它们需要通过特定的方式进行访问。
总结
双下划线在 Python 中具有多重用途。作为特殊方法名,双下划线可以自定义对象的行为;作为特殊属性名,双下划线可以提供对象的特殊属性和限制属性的功能;作为名称修饰器,双下划线可以隐藏和保护变量和方法。通过灵活运用和理解双下划线的用法,我们可以编写出更加高效和安全的 Python 程序。
参考资料: