如何使用timeit.Timer作为设置使用callable?

时间:2010-05-12 14:18:39

标签: python timeit

我想要一些依赖于某些设置的代码。设置代码看起来有点像这样:

>>> b = range(1, 1001)

我想要的代码看起来像这样:

>>> sorted(b)

除了我的代码使用与排序不同的函数。但现在这并不重要。

无论如何,只要我将字符串传递给timeit,我就知道如何计算这段代码:

>>> import timeit
>>> t = timeit.Timer("sorted(b)", "b = range(1, 1001)")
>>> min(t.repeat(3, 100))

如何使用可调用的设置并将其放入stmt可调用的可访问的命名空间中?

换句话说,我如何使用上面的代码执行相同的操作,但使用callables,而不是包含callables的字符串?

顺便提一下,这里更大的目标是重复使用单元测试中的代码来衡量性能:

import unittest
class TestSorting(unittest.TestCase):

    def setUp(self):
        self.b = range(1, 1001)

    def test_sorted(self):
        sorted(self.b)

我希望做一点工作。 timeit设置需要创建一个TestSorting实例,并且stmt代码必须以某种方式使用该特定实例。

一旦我理解了如何将时间设置放入与timeit stmt相同的命名空间中,我将研究如何将unittest.TestCase实例转换为可以直接输入timeit.Timer的内容。

马特

2 个答案:

答案 0 :(得分:1)

在2.6中,你可以“按照the docs执行”:

  

在2.6版中更改stmt和   setup参数现在也可以使用   没有可调用的对象   参数。这将嵌入调用   他们在计时器功能中会   然后由timeit()执行。注意   时间开销有点小   在这种情况下更大,因为   额外的函数调用。

您是否仍在使用旧版本的Python?在这种情况下,我建议使用Python 2.6的timer.py来源并将它们“反向移植”到您遇到的版本 - 如果该版本为2.5,则应该不会很困难(越来越难以越远)当然,回到过去。我通常不建议将此用于“生产”代码,但对于支持测试,调试,性能测量等的代码来说,这是非常好的。

答案 1 :(得分:1)

我在这里问过这个问题的一个变种,并得到了一个没有解决我问题的答案。我相信我们都没有用Pythonic来表达这个问题。

我不知道这是黑客,解决方法,还是它应该如何完成,但确实有效:

>>> import timeit
>>> b = range(1, 1001)
>>> t = timeit.Timer('sorted(b)', setup='from __main__ import b')
>>> t.repeat(3, 100)
[0.0024309158325195312, 0.0024671554565429688, 0.0024020671844482422]
# was it really running 'sorted(b)'? let's compare'
>>> t = timeit.Timer('pass', setup='from __main__ import b')
>>> t.repeat(3, 100) 
[3.0994415283203125e-06, 2.1457672119140625e-06, 1.9073486328125e-06] 
# teeny times for 'pass', 'sorted(b)' took more time

我已经读过timeit.py,它的工作原理是构造一个语句,然后使用新的命名空间调用eval(),这些命名空间似乎没有连接到你的主命名空间。请注意,由于sorted是内置的,timeit.repeat()内的eval'表达式可以访问该名称;如果是def,则必须from __main__ import b, myfunc

我希望有更多正确的方法来达到目的。