在 Python 中,类装饰器是指使用类来作为装饰器,而不是普通的函数。类装饰器的核心是 __call__ 方法(让实例可调用),或者利用 __init__ 接收被装饰对象并在内部修改或包装它。
![图片[1]_python中类装饰器的实现示例_知途无界](https://zhituwujie.com/wp-content/uploads/2026/02/d2b5ca33bd20260204104822.png)
下面我给你几个常见场景的实现示例,由浅入深。
1. 基本形式:用类包装函数(修改行为)
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Before function call")
result = self.func(*args, **kwargs)
print("After function call")
return result
@MyDecorator
def say_hello(name):
print(f"Hello, {name}")
# 调用
say_hello("Alice")
输出:
Before function call
Hello, Alice
After function call
说明:
__init__接收被装饰的函数func__call__让类的实例可以像函数一样被调用,并在调用原函数前后添加额外逻辑
2. 带参数的类装饰器
如果装饰器本身需要参数,可以用嵌套类或在 __init__ 中接收参数,并返回可调用对象。
class Repeat:
def __init__(self, times):
self.times = times
def __call__(self, func):
# 这里返回真正的包装函数(闭包)
def wrapper(*args, **kwargs):
for _ in range(self.times):
result = func(*args, **kwargs)
return result
return wrapper
@Repeat(3)
def greet(msg):
print(msg)
greet("Hi")
输出:
Hi
Hi
Hi
说明:
@Repeat(3)先实例化Repeat,__init__得到参数times=3__call__接收被装饰函数func,返回一个wrapper函数来执行多次调用
3. 装饰类(修改类的行为)
类装饰器也可以用来装饰一个类,在 __init__ 中接收类对象,并修改它的属性或方法。
class AddMethod:
def __init__(self, cls):
self.cls = cls
# 给类动态添加一个方法
cls.new_method = lambda self: "Dynamically added method!"
def __call__(self, *args, **kwargs):
# 实例化并返回
return self.cls(*args, **kwargs)
@AddMethod
class MyClass:
def __init__(self, name):
self.name = name
def hello(self):
return f"Hello from {self.name}"
obj = MyClass("Test")
print(obj.hello())
print(obj.new_method())
输出:
Hello from Test
Dynamically added method!
4. 保留原函数的元信息(functools.wraps 的类版本)
默认情况下,被装饰后的函数会丢失 __name__、__doc__ 等元数据。对于函数装饰器我们常用 @functools.wraps,在类装饰器中我们可以手动赋值或使用类似方法:
import functools
class PreserveMeta:
def __init__(self, func):
self.func = func
# 保留元数据
functools.update_wrapper(self, func)
def __call__(self, *args, **kwargs):
print("Calling", self.func.__name__)
return self.func(*args, **kwargs)
@PreserveMeta
def example():
"""Docstring of example."""
pass
print(example.__name__) # 'example'
print(example.__doc__) # 'Docstring of example.'
5. 类装饰器 vs 函数装饰器
| 特性 | 类装饰器 | 函数装饰器 |
|---|---|---|
| 状态保持 | 可用实例属性保存状态 | 需用闭包或可变默认参数 |
| 可读性 | 适合复杂逻辑/多方法 | 简单逻辑更直观 |
| 灵活性 | 可实现更复杂控制流 | 通常写法简洁 |
✅ 总结要点:
- 类装饰器通过
__init__接收被装饰对象(函数或类),通过__call__实现调用逻辑。 - 支持带参数的装饰器(在
__init__中接收参数,__call__返回包装器)。 - 可用于装饰函数或类,修改其行为或添加功能。
- 可用
functools.update_wrapper保留元数据。
如果你需要,我可以帮你画一个类装饰器的执行流程图,让理解更直观。你要看看吗?
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容