【问题标题】:How do I use timeit module inside a decorator如何在装饰器中使用 timeit 模块
【发布时间】:2022-01-06 00:34:06
【问题描述】:

我正在创建一个装饰器,主要用于 timeit 它装饰的任何功能。而且我无法正确处理。抛出max recursion depth error。有人可以帮我理解它为什么会发生以及如何实现这个 timeit 实现。 我不想使用time 模块

import timeit
from functools import wraps


def tool(func):
    """Include debug statement and timeit setup"""
    @wraps(func)
    def wrapper(*args):
        print func.__doc__, args,
        res = func(*args)
        print res
        CODE = "func{args}".format(args=args)
        times = timeit.repeat(
            stmt=CODE,
            setup="from __main__ import {func} as func".format(func=func.__name__),
            repeat=3, number=10000)
        print times
    return wrapper

【问题讨论】:

  • 可能是因为导入的东西让你得到了已经装饰的函数,你必须使用非字符串版本的 timeit 调用
  • 你的装饰函数中有timeit,所以当你调用它时,它会调用timeit,而timeit正在调用你的函数,它里面有timeit等等。所以这里有一个递归。

标签: python python-decorators


【解决方案1】:

我提到的问题是在设置中,执行该导入会为您提供已经修饰的函数,当再次执行时执行导入并获取修饰的函数并继续执行导入等等,直到它炸毁堆栈...我们不希望这样。

timeit 模块也可以将函数作为它的 stmt,因此只需构建一个 lambda 函数就可以解决问题,我们可以这样使用底层函数

stmt 和 setup 参数也可以采用不带参数的可调用对象。这会将对它们的调用嵌入到计时器函数中,然后由 timeit() 执行。请注意,在这种情况下,由于额外的函数调用,时间开销会稍大一些。

import timeit
from functools import wraps
    
def tool(func):
    """Include debug statement and timeit setup"""
    @wraps(func)
    def wrapper(*args):
        print(func.__doc__, args)
        res = func(*args)
        print(res)
        times = timeit.repeat(
            stmt=lambda: func(*args),
            repeat=3, number=10000)
        print(times)
    return wrapper

快速测试

>>> @tool
def fun():
    return 42
>>> fun()
None ()
42
[0.0013318000000026586, 0.0013294000000314554, 0.0013452000000597764]
>>> 

【讨论】:

    猜你喜欢
    • 2010-12-10
    • 2012-01-03
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    相关资源
    最近更新 更多