我正在尝试在我的Python REPL中使用python timeit
函数。它可以通过两种方式对小代码段进行计时:作为可调用的或带引号的表达式。我想知道为什么以下代码会产生不同的计时结果。
>>> import timeit
>>> timeit.timeit("lambda *args: None")
0.058281898498535156
>>> timeit.timeit(lambda *args: None)
0.0947730541229248
>>>
我的直觉告诉我,带引号的字符串变体应该有更多的“开销”,因为它需要解释,但事实并非如此。但是显然我的直觉是错误的。.
这是另一个代码段。调用可调用函数与计时引用函数语句之间并没有很大的时间差:
>>> def costly_func():
... return list(map(lambda x: x^2, range(10)))
...
>>> import timeit
>>> timeit.timeit(costly_func)
2.421797037124634
>>> timeit.timeit("list(map(lambda x: x^2, range(10)))")
2.3588619232177734
答案 0 :(得分:1)
观察:
>>> def costly():
... return list(map(str, list(range(1_000_000))))
...
>>> timeit.timeit(costly, number=100)
30.65105245400082
>>> timeit.timeit('costly', number=1_000_000_000, globals=globals())
27.45540758000061
查看number
参数。 执行功能 costly
花费了30秒。 执行表达式 costly
1'000'000'000(!)次几乎花了30秒。
为什么?因为第二个代码不执行函数costly
!它唯一执行的是表达式costly
:注意缺少括号,这意味着它不是函数调用。表达式costly
基本上是无操作的(嗯,它只需要检查当前范围内是否存在“代价昂贵”的名称,仅此而已),这就是为什么它是如此之快以及Python是否足够聪明来优化这样,表达式costly
(不是 costly()
!)的执行将是瞬间的!
在您的情况下,说lambda *args: None
只是定义一个匿名函数,对吗?当您执行这个确切的代码时,会创建一个新函数,但不会执行(为此,您应该调用它:(lambda *args: None)()
)。< / p>
因此,用"lambda *args: None"
对 string timeit.timeit("lambda *args: None")
进行计时基本上可以测试Python吐出新的匿名函数的速度。
使用timeit.timeit(lambda *args: None)
对函数本身进行计时,以测试Python可以执行一个现有的 函数的速度。
吐出新创建的功能可谓小菜一碟,而实际上运行它们可能真的很困难。
以下面的代码为例:
def Ackermann(m, n):
if m == 0:
return n + 1
if m > 0:
if n == 0:
return Ackermann(m - 1, 1)
elif n > 0:
return Ackermann(m - 1, Ackermann(m, n - 1))
如果将确切的代码放在字符串中并timeit
,将得到如下所示的信息:
>>> code = """def Ackermann(m, n):
... if m == 0:
... return 0
... if m > 0:
... if n == 0:
... return Ackermann(m - 1, 1)
... elif n > 0:
... return Ackermann(m - 1, Ackermann(m, n - 1))"""
>>> timeit.timeit(code, number=1_000_000)
0.10481472999890684
现在尝试timeit
函数本身:
>>> timeit.timeit(lambda : Ackermann(6, 4), number=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/timeit.py", line 232, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/timeit.py", line 176, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
[Previous line repeated 1 more time]
File "<stdin>", line 6, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 6, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
[Previous line repeated 983 more times]
File "<stdin>", line 6, in Ackermann
File "<stdin>", line 2, in Ackermann
RecursionError: maximum recursion depth exceeded in comparison
看-你甚至不能运行它!实际上,可能没有人可以这样做,因为它是如此的递归!
为什么第一次呼叫成功?因为它什么也没执行,所以它吐出了许多新功能,并在不久后将其全部删除。