python中类装饰器的实现示例

在 Python 中,​类装饰器是指使用类来作为装饰器,而不是普通的函数。类装饰器的核心是 __call__ 方法(让实例可调用),或者利用 __init__ 接收被装饰对象并在内部修改或包装它。

图片[1]_python中类装饰器的实现示例_知途无界

下面我给你几个常见场景的实现示例,由浅入深。


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
喜欢就点个赞,支持一下吧!
点赞38 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容