好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

47. 实现属性可修改的函数装饰器

在某项目中,程序运行效率较差,为分析程序内哪些函数执行时间开销较大,我们实现了一个带timeout参数的函数装饰器。装饰功能如下:

@warn_timeout(1.5)def func(a,b):
    ...

要求:

统计被装饰函数单次调用运行时间;

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

运行时可修稿timeout的值。

解决方案:

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

对于 nonlocal 关键字:

nonlocal 表示将变量声明为外层变量(外层函数的局部变量,而且不能是全局变量)。

global 表示将变量声明为全局变量。两个关键词都用于允许在一个局部作用域中使用外层的变量。

方案示例:
import time, logging, randomdef warn_timeout(timeout):
    def decorator(func):
        def wrap(*args, **kwargs):
            t0 = time.time()
            res = func(*args, **kwargs)
            used = time.time() - t0            if used > timeout:
                logging.warning('%s: %s > %s' % (func.__name__, used, timeout))
            return res        def set_timeout(new_timeout):
            nonlocal timeout
            timeout = new_timeout
        wrap.set_timeout = set_timeout        return wrap    return decorator

@warn_timeout(1)def f(i):
    print('in f [%s]' % i)
    while random.randint(0, 1):
        time.sleep(0.6)for i in range(10):
    f(i)f.set_timeout(1.5)for i in range(10):
    f(i)

结果:

in f [0]
in f [1]
in f [2]
in f [3]
in f [4]
WARNING:root:f: 2.40358567237854 > 1
in f [5]
in f [6]
WARNING:root:f: 1.2016241550445557 > 1
in f [7]
WARNING:root:f: 1.8050942420959473 > 1
in f [8]
in f [9]
WARNING:root:f: 1.8009305000305176 > 1
in f [0]
in f [1]
in f [2]
in f [3]
in f [4]
in f [5]
in f [6]
WARNING:root:f: 1.802403211593628 > 1.5
in f [7]
in f [8]
in f [9]

查看更多关于47. 实现属性可修改的函数装饰器的详细内容...

  阅读:34次