首先,沒有時間創建生成器表達式。創建一個生成器不會遍歷內容,所以它非常快。現貨與超過1000萬創建了一個元素生成器表達式之間的差異:
>>> print(timeit('(y for y in range(1))', number=100000))
0.060932624037377536
>>> print(timeit('(y for y in range(10000000))', number=100000))
0.06168231705669314
發電機需要更多的時間來遍歷比,說一個列表對象:
>>> from collections import deque
>>> def drain_iterable(it, _deque=deque):
... deque(it, maxlen=0)
...
>>> def produce_generator():
... return (y for y in range(100))
...
>>> print(timeit('drain_iterable(next(generators))',
... 'from __main__ import drain_iterable, produce_generator;'
... 'generators=iter([produce_generator() for _ in range(100000)])',
... number=100000))
0.5204695729771629
>>> print(timeit('[y for y in range(100)]', number=100000))
0.3088444779859856
在這裏,我在測試迭代發生器表達式僅爲discarding all elements as fast as possible。
這是因爲發生器本質上是一個函數,直到它產生一個值,然後暫停,然後再次激活下一個值,然後再次暫停。請參閱What does the "yield" keyword do?以獲得良好的概述。涉及這一過程的管理部門需要時間。相比之下,列表理解不需要花費這段時間,它可以循環所有循環,而無需重新激活和取消激活每個產生的值的函數。
發生器是高效內存,執行效率不高。他們可以節省執行時間,有時候是,但通常是因爲您避免分配和釋放更大的內存塊。
'(y for range in(100))'不會做任何事情,只能創建一個生成器對象。沒有迭代完成,所以與其他發生的事情相比,這是一個毫無價值的測試。 –
發生器的優點是在內存消耗和提前終止的可能性;迭代整個生成器不會比迭代整個相應的列表理解更快。 – user2357112