我为你准备了两个可能的解决方案。它们都是通用的运行平均函数,适用于任何数字列表(也可以适用于任何可迭代对象)。
基于生成器的:
nums = [cauchy(3,1) for x in xrange(10)]
def running_avg(numbers):
for count in xrange(1, len(nums)+1):
yield sum(numbers[:count])/count
print list(running_avg(nums))
列表推导式(实际上与先前的代码完全相同):
nums = [cauchy(3,1) for x in xrange(10)]
print [sum(nums[:count])/count for count in xrange(1, len(nums)+1)]
生成器兼容的基于生成器的:
Generator-compatabile Generator based:
编辑:我刚刚测试了一下,看看是否可以轻松地使我的解决方案与生成器兼容,并且它的性能如何。这就是我想出来的。
def running_avg(numbers):
sum = 0
for count, number in enumerate(numbers):
sum += number
yield sum/(count+1)
请看下面的性能统计数据,非常值得。
性能特征:
编辑:我还决定测试Orip有趣的多个生成器使用方式,以了解其对性能的影响。
使用timeit和以下代码(1,000,000次迭代3次):
print "Generator based:", ', '.join(str(x) for x in Timer('list(running_avg(nums))', 'from __main__ import nums, running_avg').repeat())
print "LC based:", ', '.join(str(x) for x in Timer('[sum(nums[:count])/count for count in xrange(1, len(nums)+1)]', 'from __main__ import nums').repeat())
print "Orip's:", ', '.join(str(x) for x in Timer('list(itertools.islice(running_avgs, 10))', 'from __main__ import itertools, running_avgs').repeat())
print "Generator-compatabile Generator based:", ', '.join(str(x) for x in Timer('list(running_avg(nums))', 'from __main__ import nums, running_avg').repeat())
我得到了以下的结果:
Generator based: 17.653908968, 17.8027219772, 18.0342400074
LC based: 14.3925321102, 14.4613749981, 14.4277560711
Orip's: 30.8035550117, 30.3142540455, 30.5146529675
Generator-compatabile Generator based: 3.55352187157, 3.54164409637, 3.59098005295
请参见代码的注释:
Orip's genEx based: 4.31488609314, 4.29926609993, 4.30518198013
结果以秒为单位,展示了新的兼容生成器方法相比于原来的方法持续更快。尽管您的结果可能会有所不同。我预期原始生成器和新生成器之间的巨大差异在于它们对总数的计算方式不同。