Python 函数装饰器调用

2 投票
1 回答
622 浏览
提问于 2025-04-16 15:04

我有一个函数大约被调用了1742次,但当我用一个装饰器来计算每次调用的时间时,发现它只打印了647次,我不知道为什么会这样。

更新:

  • 我这里的问题不是如何计时,而是调用次数之间的差异。我想要一个能准确记录调用次数的装饰器函数。

  • 我的Python版本是2.6,这里是我正在使用的模块 http://pastebin.com/MXu1pLWM

  • 在性能分析的输出中,我发现调用被装饰函数的调用者函数只调用了它647次,而它是唯一的调用者函数!!

搞明白了!

  • 我装饰的函数里面有一个长度为1742的循环,但实际上对这个函数的调用只有647次,尽管我还是不明白为什么调用部分显示的是1742而不是647 :)


number = 0
def timing(f):
    def wrap(*args):
        time1 = time.time()
        ret = f(*args)
        time2 = time.time()
        global number
        number+=1
        print '%s function took %0.6f ms No of calls: %s' % (f.func_name, ((time2-time1)), str(number))
        return ret
    return wrap

1 个回答

5

我看了你在pastebin上贴的代码。问题在于你把一个类的__iter__方法包裹起来了。这个方法每次循环开始时只会被调用一次。它应该立即返回一个迭代器对象——真正需要分析的是对__iter__返回的对象上调用“next”方法的次数(这个方法在每次for循环中都会被调用)。

这意味着,如果不做任何改动,你应该把你的分析工具用在__iter__内部的yield语句周围,而不是把它当作装饰器用在__iter__的调用上。

除此之外,使用timeit.timeit或者其他现成的分析工具会更好,这样可以避免一些常见的陷阱,评论中也列出了这些陷阱。

撰写回答