系统学习Python——装饰器:函数装饰器-[添加装饰器参数:基础知识]

本文探讨了如何通过装饰器参数提高Python计时器的可配置性,如添加标签和跟踪控制,以及如何通过类装饰器结构实现这一功能,使装饰器能记住函数并访问外部参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分类目录:《系统学习Python》总目录


前面文章介绍的计时器装饰器有效运行,但是如果它可配置性更强的话,就会更好一一一例如提供一个输出标签并且可以打开或关闭跟踪消息,这些在一个多用途工具中可能很有用。装饰器参数在这里派上了用场:对它们适当编写后,我们可以使用它们来指定配置选项,每个被装饰的函数都可以有各自的选项。例如,可以像下面这样添加标签:

import time
def timer(label=''):
    def decorator(func):
        def onCall(*args):
            start = time.perf_counter()
            func(*args)
            print(label, time.perf_counter() - start)
        return onCall
    return decorator

@timer('===')
def listcomp(N):
    return [x * 2 for x in range(N)]

输入:

listcomp(100)

输出:

=== 3.160000778734684e-05

这段代码添加了一个外层作用域来保存装饰器参数,以便随后真正调用的时候使用。当定义listcomp函数的时候,Python实际上调用了decorator(在真正装饰发生之前运行的timer的返回结果),其外层作用域内有着可用的值。也就是说,timer返回的装饰器,它既记住了装饰器参数又记住了最初的函数,并且返回一个可调用的onCall函数,最终这个函数在随后调用时调用最初的函数。因为这一结构创建了新的decoratoronCall函数,它们的外层作用域保留的状态与具体的装饰器相关。

我们可以把这种结构用于计时器之中,这样就能在装饰的时候传人一个标签和一个跟踪控制标志。下面是这么做的一个例子,我们可以将其编写在了一个模块文件中,以便它可以作为一个通用工具导人;它为第二个状态保留层使用了类而不是嵌套丞数,但是总的结果是相似的:

import time
def timer(label='', trace=True):
    class Timer:
        def __init__(self, func):
            self.func = func
            self.all_time = 0

        def __call__(self, *args, **kargs):
            start = time.perf_counter()
            result = self.func(*args, **kargs)
            elapsed = time.perf_counter() - start
            self.all_time += elapsed
            if trace:
                print('%s: %f, %f' % (self.func.__name__, elapsed, self.all_time))
            return result
    return Timer

我们在这里主要是把最初的Timer类嵌人一个外层函数中,以便创建一个依照不同的部署保持装饰器参数的作用域。外层的timer函数在装饰发生前调用,并且它只是返回Timer类作为实际的装饰器。在装饰时,创建了Timer的一个实例,它记住被装饰函数自身,而且还能访问位于外围函数作用域中的装饰器参数。

参考文献:
[1] Mark Lutz. Python学习手册[M]. 机械工业出版社, 2018.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

von Neumann

您的赞赏是我创作最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值