python魔法函数
Python 中的魔法方法(Magic Methods),也称为特殊方法(Special Methods)或双下方法(Dunder Methods),是以双下划线 __
开头和结尾的方法。它们用于定义类的行为,例如运算符重载、对象初始化、迭代协议等。以下是 Python 中常见的魔法方法分类及示例:
1. 对象构造与初始化
方法 | 说明 | 调用时机 |
---|---|---|
__new__(cls, ...) | 创建对象实例(构造函数) | obj = MyClass() |
__init__(self, ...) | 初始化对象 | obj = MyClass() |
__del__(self) | 对象销毁时调用 | del obj 或垃圾回收时 |
示例:
class MyClass:def __init__(self, value):self.value = valuedef __del__(self):print("对象被销毁")obj = MyClass(42) # 调用 __init__
del obj # 调用 __del__
2. 字符串表示
方法 | 说明 | 调用时机 |
---|---|---|
__str__(self) | 返回可读字符串 | str(obj) 或 print(obj) |
__repr__(self) | 返回官方字符串表示 | repr(obj) 或交互式环境 |
__format__(self, format_spec) | 格式化字符串 | format(obj, "spec") |
示例:
class Point:def __init__(self, x, y):self.x, self.y = x, ydef __str__(self):return f"Point({self.x}, {self.y})"def __repr__(self):return f"Point(x={self.x}, y={self.y})"p = Point(1, 2)
print(p) # 调用 __str__ → "Point(1, 2)"
repr(p) # 调用 __repr__ → "Point(x=1, y=2)"
3. 容器类型(列表、字典等)
方法 | 说明 | 调用时机 |
---|---|---|
__len__(self) | 返回长度 | len(obj) |
__getitem__(self, key) | 获取元素 | obj[key] |
__setitem__(self, key, value) | 设置元素 | obj[key] = value |
__delitem__(self, key) | 删除元素 | del obj[key] |
__contains__(self, item) | 检查是否包含 | item in obj |
__iter__(self) | 返回迭代器 | for x in obj |
示例:
class MyList:def __init__(self, data):self.data = list(data)def __getitem__(self, index):return self.data[index]def __len__(self):return len(self.data)lst = MyList([1, 2, 3])
print(lst[1]) # 调用 __getitem__ → 2
print(len(lst)) # 调用 __len__ → 3
4. 运算符重载
方法 | 说明 | 调用时机 |
---|---|---|
__add__(self, other) | + 加法 | obj1 + obj2 |
__sub__(self, other) | - 减法 | obj1 - obj2 |
__mul__(self, other) | * 乘法 | obj1 * obj2 |
__eq__(self, other) | == 相等 | obj1 == obj2 |
__lt__(self, other) | < 小于 | obj1 < obj2 |
__call__(self, ...) | 使对象可调用 | obj() |
示例:
class Vector:def __init__(self, x, y):self.x, self.y = x, ydef __add__(self, other):return Vector(self.x + other.x, self.y + other.y)def __eq__(self, other):return self.x == other.x and self.y == other.yv1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2 # 调用 __add__
print(v3.x, v3.y) # 4, 6
5. 上下文管理(with
语句)
方法 | 说明 | 调用时机 |
---|---|---|
__enter__(self) | 进入 with 块时调用 | with obj: ... |
__exit__(self, exc_type, exc_val, exc_tb) | 退出 with 块时调用 | with obj: ... |
示例:
class Timer:def __enter__(self):import timeself.start = time.time()def __exit__(self, *args):print(f"耗时: {time.time() - self.start:.2f}s")with Timer():time.sleep(1) # 自动计算时间
6. 属性访问控制
方法 | 说明 | 调用时机 |
---|---|---|
__getattr__(self, name) | 访问不存在的属性时调用 | obj.unknown |
__setattr__(self, name, value) | 设置属性时调用 | obj.x = 1 |
__delattr__(self, name) | 删除属性时调用 | del obj.x |
__getattribute__(self, name) | 访问任何属性时调用 | obj.x |
示例:
class DynamicAttributes:def __getattr__(self, name):return f"属性 {name} 不存在"obj = DynamicAttributes()
print(obj.foo) # 调用 __getattr__ → "属性 foo 不存在"
7. 迭代器协议
方法 | 说明 | 调用时机 |
---|---|---|
__iter__(self) | 返回迭代器 | for x in obj |
__next__(self) | 返回下一个值 | next(iter_obj) |
示例:
class CountDown:def __init__(self, start):self.current = startdef __iter__(self):return selfdef __next__(self):if self.current <= 0:raise StopIterationself.current -= 1return self.current + 1for num in CountDown(3):print(num) # 3, 2, 1
总结
Python 的魔法方法使得自定义类的行为更加灵活,例如:
- 运算符重载(
+
,-
,==
) - 容器模拟(
len()
,[]
,for
循环) - 上下文管理(
with
语句) - 属性控制(动态属性访问)
掌握这些方法可以让你写出更 Pythonic 的代码!