9-4修改属性的装饰器

来源:互联网 发布:在iphone编程 编辑:程序博客网 时间:2024/05/16 14:47
# -*- coding:utf-8 -*-'''为分析程序内哪些函数执行时间开销较大,定义一个timeout参数的函数装饰器.装饰功能:1.统计被装饰函数单词调用运行时间.2.时间大于参数timeout的,将此次函数调用记录到log日志中.3.运行时可修改timeout的值.解决方案:为包裹函数增添一个函数,用来修改闭包中使用的自由变量.在python3中:使用nonlocal访问嵌套作用域中的变量引用'''from functools import wrapsimport timeimport loggingfrom random import randintdef warn(timeout):    def decorator(func):        @wraps(func)        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)            return res        def setTimeout(k):            # timeout = k            # 这样是不允许的,因为timeout是在函数wrapper闭包内使用的自由变量            # 此句只会在setTimeout()创建一个属于本函数的本地变量            nonlocal timeout      # 类似于global的关键字,使用在嵌套作用域下            timeout = k        wrapper.setTimeout = setTimeout   # 将setTimeout()函数作为wrapper的属性        return wrapper    return decorator# 因为python-2不支持nolocal关键字,所以做以下处理def warn1(timeout):    timeout = [timeout]         # attr -> [attr,]    def decorator(func):        @wraps(func)        def wrapper(*args, **kwargs):            start = time.time()            res = func(*args, **kwargs)            used = time.time() - start            if used > timeout[0]:                msg = '"%s": %s > %s' % (func.__name__, used, timeout[0])  # timeout -> timeout[0]                logging.warn(msg)            return res        def setTimeout(k):            timeout[0] = k          # timeout -> timeout[0]        wrapper.setTimeout = setTimeout   # 将setTimeout()函数作为wrapper的属性        return wrapper    return decorator@warn1(1.5)def test():    print('IN test')    while randint(0, 1):        time.sleep(0.5)if __name__ == '__main__':    for _ in range(30):        test()    test.setTimeout(1)    for _ in range(30):        test()
0 0
原创粉丝点击