魔术方法(Magic Methods)以__开头和结尾,是 Python 实现面向对象特性的核心机制。它们由解释器自动调用,无需手动触发,用于赋予对象特殊行为(如运算符重载、容器模拟、上下文管理等)。
一、构造与初始化相关
|
方法名称 |
触发条件 |
主要应用场景 |
|
__new__(cls) |
创建实例时最先调用(在__init__之前),返回实例对象 |
自定义实例创建逻辑(如单例模式、不可变对象初始化) |
|
__init__(self) |
实例创建后初始化调用,接收参数并赋值给实例属性 |
初始化实例属性,设置对象初始状态 |
|
__del__(self) |
实例被垃圾回收时调用(析构函数) |
释放资源(如关闭文件、数据库连接),注意:不保证必定会被及时调用 |
示例:
python
运行
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
self.value = 0
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True(单例模式)
二、字符串表明相关
|
方法名称 |
触发条件 |
主要应用场景 |
|
__str__(self) |
print(obj)、str(obj)时调用 |
定义对象的 “友善字符串表明”(面向用户) |
|
__repr__(self) |
repr(obj)、交互式解释器中输出对象时调用 |
定义对象的 “官方字符串表明”(面向开发者,要求可还原对象) |
示例:
python
运行
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Person({self.name}, {self.age})" # 用户友善
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})" # 可还原对象
p = Person("Alice", 25)
print(p) # Person(Alice, 25)(__str__)
print(repr(p)) # Person(name='Alice', age=25)(__repr__)
三、运算符重载相关
1. 算术运算符
|
方法名称 |
触发条件 |
主要应用场景 |
|
__add__(self, other) |
self + other |
自定义加法逻辑 |
|
__sub__(self, other) |
self – other |
自定义减法逻辑 |
|
__mul__(self, other) |
self * other |
自定义乘法逻辑 |
|
__truediv__(self, other) |
self / other |
自定义除法逻辑 |
|
__mod__(self, other) |
self % other |
自定义取模逻辑 |
2. 比较运算符
|
方法名称 |
触发条件 |
主要应用场景 |
|
__eq__(self, other) |
self == other |
自定义相等判断 |
|
__ne__(self, other) |
self != other |
自定义不等判断 |
|
__lt__(self, other) |
self < other |
自定义小于判断 |
|
__gt__(self, other) |
self > other |
自定义大于判断 |
|
__le__(self, other) |
self <= other |
自定义小于等于判断 |
|
__ge__(self, other) |
self >= other |
自定义大于等于判断 |
示例:
python
运行
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __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.y
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # <__main__.Vector object at 0x...>(需配合__str__)
print(v1 == Vector(1,2)) # True
四、容器类型模拟
用于让自定义对象像列表、字典等容器一样工作。
|
方法名称 |
触发条件 |
主要应用场景 |
|
__len__(self) |
len(obj)时调用 |
定义容器的 “长度” 计算逻辑 |
|
__getitem__(self, key) |
obj[key]时调用(获取元素) |
支持索引 / 键访问元素(如列表的obj[0]、字典的obj['key']) |
|
__setitem__(self, key, value) |
obj[key] = value时调用(设置元素) |
支持索引 / 键赋值 |
|
__delitem__(self, key) |
del obj[key]时调用(删除元素) |
支持删除指定索引 / 键的元素 |
|
__contains__(self, item) |
item in obj时调用 |
支持in运算符判断元素是否存在 |
示例:
python
运行
class CustomList:
def __init__(self):
self.data = []
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
return self.data[idx]
def __setitem__(self, idx, value):
self.data[idx] = value
def __contains__(self, item):
return item in self.data
cl = CustomList()
cl.data = [1,2,3]
print(len(cl)) # 3
print(cl[0]) # 1
cl[0] = 10
print(2 in cl) # True
五、可调用对象模拟
|
方法名称 |
触发条件 |
主要应用场景 |
|
__call__(self, *args, **kwargs) |
将实例作为函数调用(obj()或obj(args)) |
让对象具备 “函数行为”(如装饰器、状态保持的可调用对象) |
示例:
python
运行
class Counter:
def __init__(self):
self.count = 0
def __call__(self):
self.count += 1
return self.count
c = Counter()
print(c()) # 1
print(c()) # 2(调用实例时更新状态)
六、上下文管理器(with 语句)
|
方法名称 |
触发条件 |
主要应用场景 |
|
__enter__(self) |
进入with语句块时调用,返回上下文对象 |
初始化资源(如打开文件、连接数据库) |
|
__exit__(self, exc_type, exc_val, exc_tb) |
退出with语句块时调用,接收异常信息(若有) |
释放资源(如关闭文件、回滚事务),处理异常 |
示例:
python
运行
class FileHandler:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
with FileHandler("test.txt", "w") as f:
f.write("Hello") # 自动打开/关闭文件
七、属性访问控制
用于自定义属性的获取、设置、删除逻辑。
|
方法名称 |
触发条件 |
主要应用场景 |
|
__getattr__(self, name) |
访问不存在的属性时调用(obj.name) |
动态生成属性、处理属性不存在的情况 |
|
__getattribute__(self, name) |
访问任意属性时优先调用(覆盖默认属性查找) |
全局控制属性访问(需谨慎使用,避免递归) |
|
__setattr__(self, name, value) |
设置属性时调用(obj.name = value) |
验证属性赋值、拦截属性设置 |
|
__delattr__(self, name) |
删除属性时调用(del obj.name) |
控制属性删除逻辑 |
示例:
python
运行
class SafeDict:
def __init__(self):
self._data = {}
def __getattr__(self, name):
return self._data.get(name, f"属性{name}不存在")
def __setattr__(self, name, value):
if name.startswith("_"):
super().__setattr__(name, value) # 避免递归
else:
self._data[name] = value
sd = SafeDict()
sd.name = "Alice"
print(sd.name) # Alice
print(sd.age) # 属性age不存在
八、迭代器相关
用于让对象支持迭代(如for…in循环)。
|
方法名称 |
触发条件 |
主要应用场景 |
|
__iter__(self) |
调用iter(obj)时触发,返回迭代器对象 |
定义对象的迭代逻辑,返回自身或其他迭代器 |
|
__next__(self) |
调用next(obj)时触发,返回下一个元素 |
实现迭代器的 “下一个元素” 获取逻辑,无元素时抛出StopIteration |
示例:
python
运行
class MyRange:
def __init__(self, start, end):
self.start = start
self.end = end
def __iter__(self):
return self # 返回自身作为迭代器
def __next__(self):
if self.start >= self.end:
raise StopIteration
current = self.start
self.start += 1
return current
for i in MyRange(1, 4):
print(i) # 1 2 3
九、其他常用魔术方法
|
方法名称 |
触发条件 |
主要应用场景 |
|
__hash__(self) |
调用hash(obj)时触发,返回哈希值 |
让对象可作为字典的键、集合的元素(需配合__eq__) |
|
__bool__(self) |
调用bool(obj)或判断对象真假时触发(如if obj:) |
定义对象的 “真假” 判断逻辑 |
|
__copy__(self) |
调用copy.copy(obj)时触发 |
实现浅拷贝逻辑 |
|
__deepcopy__(self, memo) |
调用copy.deepcopy(obj)时触发 |
实现深拷贝逻辑 |
示例:
python
运行
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __hash__(self):
return hash((self.x, self.y)) # 基于坐标生成哈希值
def __bool__(self):
return self.x != 0 or self.y != 0 # 坐标全0时为False
p1 = Point(1, 2)
p2 = Point(0, 0)
print(hash(p1)) # 哈希值
print(bool(p1)) # True
print(bool(p2)) # False
总结
魔术方法是 Python 面向对象的 “黑魔法”,通过实现这些方法,能让自定义对象拥有 Python 内置类型的行为特性。核心要点:
- 魔术方法由解释器自动调用,无需手动调用;
- 不同魔术方法对应不同的场景(如运算符、容器、上下文管理);
- 合理使用魔术方法可大幅提升代码的简洁性和可读性,让自定义类更 “Pythonic”。

收藏了,感谢分享