温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2022-03-23 10:32:34 来源:亿速云 阅读:435 作者:小新 栏目:web开发

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

尝试用类来实现装饰器

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

# 使用 callable 可以检测某个对象是否“可被调用”
>>> def foo(): pass
...
>>> type(foo)
<class 'function'>
>>> callable(foo)
True

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

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

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

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

import time
import functools
class DelayFunc:
    def __init__(self,  duration, func):
        self.duration = duration
        self.func = func
def __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如何使用类来实现装饰器”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI