如何使用可调用对象作为 timeit.Timer 的设置?
我想对一些依赖于某些设置的代码进行计时。设置代码看起来有点像这样:
>>> 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 的内容。
马特
I want to time some code that depends on some setup. The setup code looks a little like this:
>>> b = range(1, 1001)
And the code I want to time looks vaguely like this:
>>> sorted(b)
Except my code uses a different function than sorted. But that ain't important right now.
Anyhow, I know how to time this code as long as I pass in strings to timeit:
>>> import timeit
>>> t = timeit.Timer("sorted(b)", "b = range(1, 1001)")
>>> min(t.repeat(3, 100))
How do I use a setup callable and have it put stuff into the namespace that the stmt callable can access?
In other words, how do I do the same thing as the code above, but with callables, and not strings containing callables?
Incidentally, the bigger goal here is to reuse code from my unit tests to measure performance:
import unittest
class TestSorting(unittest.TestCase):
def setUp(self):
self.b = range(1, 1001)
def test_sorted(self):
sorted(self.b)
I expect to do a little work. The timeit setup will need to make an instance of TestSorting and somehow the stmt code will have to use that particular instance.
Once I understand how to have the timeit setup put stuff into the same namespace as the timeit stmt, I'll look into how to translate unittest.TestCase instances into something that can feed right into timeit.Timer.
Matt
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 2.6 中,您可以根据 文档“直接执行” :
您是否还在使用旧版本的 Python?在这种情况下,我建议采用 Python 2.6 的
timer.py
源代码并将它们“反向移植”到您所使用的版本 - 如果该版本是 2.5,那么应该不难(变得更难)当然,你需要回到过去的距离越远)。我通常不建议将其用于“生产”代码,但对于支持测试、调试、性能测量等的代码来说,它非常好。In 2.6, you can "just do it", per the docs:
Are you stuck using an old version of Python? In that case, I would suggest taking Python 2.6's
timer.py
sources and "backporting" them to the version you're stuck with -- should not be difficult if that version is 2.5 (gets harder the farther you need to travel back in time, of course). I would generally not recommend this for "production" code, but it's quite fine for code that supports testing, debugging, performance measurements, and the like.我在这里问了这个问题的一个变体,也得到了一个没有解决我的问题的答案。我相信我们都未能用 Pythonic 的术语来阐明这个问题。
我不知道这是否是一个黑客,解决方法,或者它应该如何完成,但它确实有效:
我已阅读 timeit.py,它通过构造一个语句然后调用 eval() 使用新的命名空间(似乎)与主命名空间没有连接。请注意,由于
sorted
是内置函数,因此timeit.repeat()
内的 eval'ed 表达式可以访问该名称;如果它是你的def
,你必须from __main__ import b, myfunc
。我希望有比这更合适的方法来达到目的。
I've asked a variant of this question here and also got an answer that didn't solve my problem. I believe we are both failing to articulate the problem in terms Pythonic.
I don't know if this is a hack, workaround, or how it is supposed to be done, but it does work:
I have read timeit.py, it works by constructing a statement and then calls eval() on it using new namespaces which have (seemingly) no connection to your main namespace. Note that since
sorted
is a built-in, the eval'ed expression insidetimeit.repeat()
has access to the name; if it was yourdef
you'd have tofrom __main__ import b, myfunc
.I hope there is more proper way than this to achieve the end.