以下两个代码段(A&B)都返回两个字典的交集。在
下面两个代码片段都应该在O(n)中运行并输出相同的结果。不过,python代码段B的运行速度似乎更快。这些代码片段来自Python食谱。
代码段A:
def simpleway():
result = []
for k in to500.keys():
if evens.has_key(k):
result.append(k)
return result
代码段B:
^{pr2}$一些设置逻辑和用于为两个函数计时的函数=>
to500 = {}
for i in range(500): to500[i] = 1
evens = {}
for i in range(0,1000,2): evens[i] = 1
def timeo(fun, n=1000):
def void(): pass
start = time.clock()
for i in range(n): void()
stend = time.clock()
overhead = stend - start
start = time.clock()
for i in range(n): fun()
stend = time.clock()
thetime = stend - start
return fun.__name__, thetime - overhead
使用2.3 Ghz Ivy Bridge四核处理器(OS X 10.8.4)的Python2.7.5
我明白了
>>> timeo(simpleway)
('simpleway', 0.08928500000000028)
>>> timeo(pythonicsimpleway)
('pythonicsimpleway', 0.04579400000000078)
他们做的事情并不完全一样,第一个做的工作要多得多:
.has_key()
和{list comprehension在一个one操作中创建python list对象之前,收集C数组中所有生成的元素。在
这两个函数确实产生了相同的结果,一个只是不必要的慢。在
如果您想深入了解细节,请查看使用
dis
模块的字节码反汇编:对于显式for循环,每次迭代的字节码指令数要大得多。}。在
simpleway
循环每次迭代必须执行11条指令(如果.has_key()
为真),而列表理解则为7条,其中额外的指令主要覆盖LOAD_ATTR
和{如果要使第一个版本更快,请将
^{pr2}$.has_key()
替换为in
测试,直接在字典上循环并将.append()
属性缓存到一个局部变量中:然后使用
^{3}$timeit
模块正确地测试计时(重复运行,您的平台最精确的计时器):这里
simpleway_optimized
正在快速接近列表理解方法,但是后者仍然可以通过一步构建python列表对象来获胜。在相关问题 更多 >
编程相关推荐