【问题标题】:How to use a callable as the setup with timeit.Timer?如何使用可调用作为 timeit.Timer 的设置?
【发布时间】:2010-05-12 14:18:38
【问题描述】:

我想为一些取决于某些设置的代码计时。设置代码看起来有点像这样:

>>> b = range(1, 1001)

而我想要计时的代码看起来是这样的:

>>> sorted(b)

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

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

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

如何使用 setup callable 并将其放入 stmt callable 可以访问的命名空间?

换句话说,我如何做与上面的代码相同的事情,但使用可调用对象,而不是包含可调用对象的字符串?

顺便说一句,这里更大的目标是重用我的单元测试中的代码来衡量性能:

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 设置将内容放入与 timeit stmt 相同的命名空间中,我将研究如何将 unittest.TestCase 实例转换为可以直接输入 timeit.Timer 的内容。

马特

【问题讨论】:

    标签: python timeit


    【解决方案1】:

    在 2.6 中,您可以“照做”,the docs

    在 2.6 版中更改stmtsetup 参数现在也可以带 无需调用即可调用的对象 论据。这将嵌入调用 他们在一个定时器功能,将 然后由timeit() 执行。笔记 时间开销有点小 在这种情况下更大,因为 额外的函数调用。

    您是否还在使用旧版本的 Python?在这种情况下,我建议使用 Python 2.6 的 timer.py 源并将它们“反向移植”到您坚持使用的版本——如果该版本是 2.5 应该不难(越远,您需要返回越难)当然,及时)。对于“生产”代码,我通常不会推荐此方法,但对于支持测试、调试、性能测量等的代码来说,它是相当不错的。

    【讨论】:

    • 抱歉,我应该更清楚地说明我的问题。我抱怨我不知道如何让 setup callable 在 stmt 代码使用的命名空间中创建一些东西。在字符串示例中,设置字符串创建了一个在语句代码中可见的对象“b”。我很困惑如何对可调用对象做同样的事情。我不知道如何让 setup callable 创建那个“b”对象,以便 stmt callable 可以看到它。
    • 这篇帖子stackoverflow.com/questions/1966750/… 显示了一个设置语句的示例,该示例将内容添加到语句代码使用的命名空间中。我将问题更进一步,并尝试使用可调用对象而不是字符串来完成这一切。
    • 有没有办法使用带参数的可调用对象?
    • @endolith:你可以使用像 lambda: foo(56) 这样的可调用对象,但它会增加一些开销
    【解决方案2】:

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

    我不知道这是否是一种 hack、解决方法或应该如何完成,但它确实有效:

    >>> 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

    我希望有比这更合适的方法来达到目的。

    【讨论】:

      猜你喜欢
      • 2011-07-02
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 2017-12-05
      • 2021-11-07
      • 1970-01-01
      相关资源
      最近更新 更多