Python中的timeit模块无法识别numpy模块。

15

我想测试两个相同列表之间的处理时间,具体来说是普通列表和numpy列表。我的代码如下:

import timeit
import numpy as np

t = timeit.Timer("range(1000)")
print t.timeit()

u = timeit.Timer("np.arange(1000)")
print u.timeit()

计算 t 没问题,但是对于 u,出现了 NameError: global name 'np' is not defined。

我该如何编写代码来获取处理时间?

3个回答

16

timeit.Timer类有两种使用方式。

它可以接受需要编译和执行的源代码——此时,代码将在一个仅运行setup代码的新环境中执行;或者可以接受一个可调用对象,在这种情况下,该可调用对象就像任何其他可调用对象一样在当前环境中被调用。

因此,您有两个选项:

u = timeit.Timer("np.arange(1000)", setup='import numpy as np')

…或者…

u = timeit.Timer(lambda: np.arange(1000))
在第一种情况下,你恰好做了一个import numpy as np是无关紧要的;它对编译和执行np.arange(1000)的环境没有影响(因此你必须在setup=...中包含它)。
在第二种情况下,你做了一个import numpy as np是显然相关的——它会影响你的代码被评估的环境,包括lambda: np.arange(1000)

5
使用setup参数:
u = timeit.Timer("np.arange(1000)", setup='import numpy as np')

谢谢你提供代码。现在我知道时间了,你知道为什么普通列表的时间(10.4秒)比数组(1.9秒)长得多吗? - user3211991
@user3211991 range(1000) 在内存中创建列表,请尝试将 range(1000) 替换为 xrange(1000),参考 https://dev59.com/m3VD5IYBdhLWcg3wE3bz。 - ndpu
请参见https://dev59.com/FWgv5IYBdhLWcg3wTvE-,了解range和np.arange之间效率的更多细节。 - Ffisegydd
@user3211991:那真的是一个完全不同的问题...但一般来说,创建1000个Python int对象以及一个用于保存它们的列表将比创建和初始化1000个C int对象的数组需要更长的时间。这就是NumPy的半个优点——不在Python对象中“装箱”每个值可以节省所有装箱和拆箱的时间。(另一个优点是它还可以节省这1000个“盒子”的内存。第三个优点——因为NumPy足够酷,拥有超过100%的好处——是它提供了逐元素操作的良好API。) - abarnert

4
要在 timeit 中使用导入的库,您需要使用 setup 关键字参数进行导入(文档):
import timeit

# Doesn't require setup kwarg as range doesn't need to be imported.
t = timeit.Timer("range(1000)")
print t.timeit()

# Requires the import of numpy (as np) through the setup kwarg.
u = timeit.Timer("np.arange(1000)", setup = 'import numpy as np')
print(u.timeit())
< p > < code > setup 关键参数允许您设置代码,例如通过使用< code > from__main__import func 导入外部库或从您的代码导入函数。


2
不,你不必使用 setup 关键字参数导入它们。如果你传递一个可调用对象而不是要编译的代码,则这个可调用对象已经在你的普通环境中编译过了(包括任何 import 语句),并且可以正常运行。 - abarnert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接