我预计在多个循环的情况下,列表迭代要比使用生成器快得多,我的代码表明这是错误的。
我的理解是(操作是指定义元素的任何表达式):
我使用以下代码检查了我的期望:
from timeit import timeit
def pow2_list(n):
"""Return a list with powers of 2"""
results = []
for i in range(n):
results.append(2**i)
return results
def pow2_gen(n):
"""Generator of powers of 2"""
for i in range(n):
yield 2**i
def loop(iterator, n=1000):
"""Loop n times over iterable object"""
for _ in range(n):
for _ in iterator:
pass
l = pow2_list(1000) # point to a list
g = pow2_gen(1000) # point to a generator
time_list = \
timeit("loop(l)", setup="from __main__ import loop, l", number=10)
time_gen = \
timeit("loop(g)", setup="from __main__ import loop, g", number=10)
print("Loops over list took: ", time_list)
print("Loops over generator took: ", time_gen)结果让我吃惊..。
Loops over list took: 0.20484769299946493
Loops over generator took: 0.0019217690005461918不知何故,即使在循环1000次以上时,使用生成器的速度也比列表快得多。在这种情况下,我们讨论的是两个数量级!为什么?
编辑:
谢谢你的回答。现在我看到了我的错误。我错误地认为生成器从一个新的循环开始,就像range:
>>> x = range(10)
>>> sum(x)
45
>>> sum(x)
45但这太天真了(range不是发电机.)
关于可能重复的注释:我的问题涉及生成器上的多个循环,这在另一个线程中没有解释。
发布于 2016-11-25 15:06:13
你的考试有问题。也就是说,生成器是不可重用的。一旦筋疲力尽,就不能再使用它,必须生成一个新的。例如:
l = [0, 1, 2, 4, 5]
g = iter(l) # creates an iterator (a type of generator) over the list
sum_list0 = sum(l)
sum_list1 = sum(1)
assert sum_list0 == sum_list1 # all working normally
sum_gen0 = sum(g) # consumes generator
sum_gen1 = sum(g) # sum of empty generator is 0
assert sum_gen0 == sum_list1 # result is correct
assert sum_gen1 == sum_list1, "second result was incorrect" # because generator was exhausted要使测试正常运行,必须在传递给timeit的语句中重新创建生成器。
from timeit import timeit
n = 1000
repeats = 10000
list_powers = [2**i for i in range(n)]
def gen_powers():
for i in range(n):
yield 2**i
time_list = timeit("min(list_powers)", globals=globals(), number=repeats)
time_gen = timeit("min(gen_powers())", globals=globals(), number=repeats)
print("Loops over list took: ", time_list)
print("Loops over generator took: ", time_gen)给予:
Loops over list took: 0.24689035064701784
Loops over generator took: 13.551637053904571现在,发生器比列表慢两个数量级。这是预期的,因为与序列上的迭代次数相比,序列的大小很小。如果n很大,那么列表的创建就会变慢。这是因为在追加新项时如何展开列表,以及创建时未传递给列表的最终大小。与生成器相比,增加迭代次数将加快列表的速度,因为生成器所需的工作量增加,而对于列表,则保持不变。由于n只有1000 (小),而repeats占n的主导地位,那么生成器就会慢一些。
https://stackoverflow.com/questions/40807277
复制相似问题