9-4修改属性的装饰器

    xiaoxiao2021-03-25  47

    # -*- coding:utf-8 -*- ''' 为分析程序内哪些函数执行时间开销较大,定义一个timeout参数的函数装饰器.装饰功能: 1.统计被装饰函数单词调用运行时间. 2.时间大于参数timeout的,将此次函数调用记录到log日志中. 3.运行时可修改timeout的值. 解决方案: 为包裹函数增添一个函数,用来修改闭包中使用的自由变量. 在python3中:使用nonlocal访问嵌套作用域中的变量引用 ''' from functools import wraps import time import logging from random import randint def 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()
    转载请注明原文地址: https://ju.6miu.com/read-150191.html

    最新回复(0)