在回答问题Clunky calculation of differences between an incrementing set of numbers, is there a more beautiful way?时,我想出了两个解决方案,一个使用List Comprehension
,另一个使用itertools.starmap
。当`starmap`优先于`List Comprehension`时
对我来说,list comprehension
语法看起来更清晰,更易读,更简洁且更具Pythonic。但仍然starmap
在itertools中可用,我想知道,它必须有一个原因。
我的问题是当starmap
可能优于List Comprehension
?
注意如果其风格的问题,然后它绝对违背There should be one-- and preferably only one --obvious way to do it.
头对头比较
可读性计数。 --- LC
它再次是一个知觉问题,但对我来说LC
比starmap
更具可读性。 要使用starmap
,要么需要导入operator
,要么定义lambda
或某种明确的multi-variable
函数,但仍需从itertools
额外导入。
性能 --- LC
>>> def using_star_map(nums):
delta=starmap(sub,izip(nums[1:],nums))
return sum(delta)/float(len(nums)-1)
>>> def using_LC(nums):
delta=(x-y for x,y in izip(nums[1:],nums))
return sum(delta)/float(len(nums)-1)
>>> nums=[random.randint(1,10) for _ in range(100000)]
>>> t1=Timer(stmt='using_star_map(nums)',setup='from __main__ import nums,using_star_map;from itertools import starmap,izip')
>>> t2=Timer(stmt='using_LC(nums)',setup='from __main__ import nums,using_LC;from itertools import izip')
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=1000)/100000)
235.03 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=1000)/100000)
181.87 usec/pass
我不认为按照您的方式比较它们是公平的。这两个函数都应该将差异保存为'deltas',因为目前''use_star_map'由于它全部在一行中而不易读。改为:'deltas = starmap(sub,zip(nums [1:],nums))'sum(deltas)/ float(len(nums)-1)' – jamylak
@jamylak:谢谢你指出。但不幸的是,它不会改变性能差异。 – Abhijit
这不是我们的意思,但我们也在谈论可读性。 – jamylak