python高级(如何实现属性可修改的函数装饰器)

案例:

为分析程序内哪些函数执行时间开销较大,我们定义一个带timeout参数的函数装饰器。装饰功能如下:

1.统计被装饰函数单次调用运行时间。

2.时间大于参数timeout的,将此次函数调用记录到log日志当中。

3.运行时间可修改timeout的值。

 

为包裹函数增添一个函数,用来修改闭包中使用的自由变量。在python3中,使用nonlocal访问嵌套作用域中的变量引用

from functools import wraps
from random import randint
import time
import logging   #导入日志模块

def warn(timeout):
    def decorator(func):
        @wraps(func)   #被装饰器装饰后的函数,函数名等函数属性的指向会发生改变,利用wraps把副作用给消除,指向保留原有函数的名称和属性
        def wrapper(*args,**kwargs):
            start = time.time()
            res = func(*args,**kwargs)
            used = time.time() - start   #计算运行用时
            if used > timeout:
                msg = '%s : %s > %s' %(func.__name__,used,timeout)
                logging.warn(msg)   #把运行超时的记录写进log日志中
            return res
        def setTimeout(k):   #给用户自定义超时时间
            nonlocal timeout   #timeout为当前闭包内使用的私有变量,使用nonlocal访问嵌套作用域中的变量引用
            timeout = k
        wrapper.setTimeout = setTimeout  #把函数作为warpper属性,用户可以通过调用设置timeout超时
        return wrapper
    return decorator

@warn(1.5)   #语法糖装饰,传入时间参数
def test():
    print('in test')
    while randint(0,1):
        time.sleep(0.5)

for _ in range(30):
    test()
    
test.setTimeout(1)   #自定义改变超时时间
for _ in range(30):
    test()

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值