千家信息网

python如何使用类来实现装饰器

发表于:2025-01-22 作者:千家信息网编辑
千家信息网最后更新 2025年01月22日,这篇文章主要介绍python如何使用类来实现装饰器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!尝试用类来实现装饰器绝大多数装饰器都是基于函数和 闭包 实现的,但这并非制造装饰
千家信息网最后更新 2025年01月22日python如何使用类来实现装饰器

这篇文章主要介绍python如何使用类来实现装饰器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

尝试用类来实现装饰器

绝大多数装饰器都是基于函数和 闭包 实现的,但这并非制造装饰器的唯一方式。事实上,Python 对某个对象是否能通过装饰器(@decorator)形式使用只有一个要求:decorator 必须是一个"可被调用(callable)的对象。

# 使用 callable 可以检测某个对象是否"可被调用">>> def foo(): pass...>>> type(foo)>>> callable(foo)True

函数自然是"可被调用"的对象。但除了函数外,我们也可以让任何一个类(class)变得"可被调用"(callable)。办法很简单,只要自定义类的 __call__ 魔法方法即可。

class Foo:    def __call__(self):        print("Hello, __call___")foo = Foo()# OUTPUT: Trueprint(callable(foo))# 调用 foo 实例# OUTPUT: Hello, __call__foo()

基于这个特性,我们可以很方便的使用类来实现装饰器。

下面这段代码,会定义一个名为 @delay(duration) 的装饰器,使用它装饰过的函数在每次执行前,都会等待额外的 duration 秒。同时,我们也希望为用户提供无需等待马上执行的 eager_call 接口。

import timeimport functoolsclass DelayFunc:    def __init__(self,  duration, func):        self.duration = duration        self.func = funcdef __call__(self, *args, **kwargs):        print(f'Wait for {self.duration} seconds...')        time.sleep(self.duration)        return self.func(*args, **kwargs)def eager_call(self, *args, **kwargs):        print('Call without delay')        return self.func(*args, **kwargs)def delay(duration):    """装饰器:推迟某个函数的执行。同时提供 .eager_call 方法立即执行    """    # 此处为了避免定义额外函数,直接使用 functools.partial 帮助构造    # DelayFunc 实例    return functools.partial(DelayFunc, duration)如何使用装饰器的样例代码:@delay(duration=2)def add(a, b):    return a + b# 这次调用将会延迟 2 秒add(1, 2)# 这次调用将会立即执行add.eager_call(1, 2)

@delay(duration) 就是一个基于类来实现的装饰器。当然,如果你非常熟悉 Python 里的函数和闭包,上面的 delay 装饰器其实也完全可以只用函数来实现。所以,为什么我们要用类来做这件事呢?

与纯函数相比,我觉得使用类实现的装饰器在特定场景下有几个优势:

• 实现有状态的装饰器时,操作类属性比操作闭包内变量更符合直觉、不易出错

• 实现为函数扩充接口的装饰器时,使用类包装函数,比直接为函数对象追加属性更易于维护

• 更容易实现一个同时兼容装饰器与上下文管理器协议的对象

以上是"python如何使用类来实现装饰器"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0