在以不同方式构建列表时,我注意到一些有趣的行为。 .append
比列表推导需要更长的时间,而列表推导需要的时间超过map
,如下面的实验所示:
def square(x): return x**2
def appendtime(times=10**6):
answer = []
start = time.clock()
for i in range(times):
answer.append(square(i))
end = time.clock()
return end-start
def comptime(times=10**6):
start = time.clock()
answer = [square(i) for i in range(times)]
end = time.clock()
return end-start
def maptime(times=10**6):
start = time.clock()
answer = map(square, range(times))
end = time.clock()
return end-start
for func in [appendtime, comptime, maptime]:
print("%s: %s" %(func.__name__, func()))
Python 2.7:
appendtime: 0.42632
comptime: 0.312877
maptime: 0.232474
Python 3.3.3:
appendtime: 0.614167
comptime: 0.5506650000000001
maptime: 0.57115
现在,我非常清楚python 2.7中的range
构建了一个列表,所以我知道为什么python 2.7和3.3中相应函数的时间之间存在差异。我更关心的是append
,列表理解和map
之间的相对时差。
首先,我认为这可能是因为map
和列表推导可以让译员知道结果列表的最终大小,这将允许解释器在引擎盖下malloc一个足够大的C数组存储列表。按照这种逻辑,列表推导和map
应该花费相同的时间
但是,时序数据显示,在python 2.7中,listcomps的速度比append
快〜1.36倍,而map
的速度比listcomps快〜1.34倍。
更奇怪的是,在python 3.3中,listcomps的速度是append
的1.12倍,而map
实际上比listcomps慢。
显然,map
和listcomps不会“遵循相同的规则”;很明显,地图利用了listcomps没有的东西
任何人都可以了解这些时间价值差异背后的原因吗?
答案 0 :(得分:1)
首先,在python3.x中,map
返回iterable
,而不是列表,这样就解释了50kx的加速比。为了使它成为合理的时机,在python3.x中你需要list(map(...))
。
其次,.append
会慢一些,因为每次循环时,解释器需要查找列表,然后需要在列表中查找append
函数。使用list-comp或map不需要进行额外的.append
查找。
最后,通过list-comprehension,我相信在循环的每个回合都需要查找函数square
。使用地图时,只有在调用地图时才会查找,这就是为什么如果你在列表理解中调用函数,map
通常会更快。请注意,列表理解通常会使用map
函数击败lambda
。