2008-12-13 27 views

回答

94

你瞭解列表解析嗎?如果是這樣,一個生成器表達式就像列表理解一樣,但不是找到你感興趣的所有項目並將它們打包到列表中,而是等待,並逐個從表達式中逐項生成每個項目。

>>> my_list = [1, 3, 5, 9, 2, 6] 
>>> filtered_list = [item for item in my_list if item > 3] 
>>> print filtered_list 
[5, 9, 6] 
>>> len(filtered_list) 
3 
>>> # compare to generator expression 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> print filtered_gen # notice it's a generator object 
<generator object at 0xb7d5e02c> 
>>> len(filtered_gen) # So technically, it has no length 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: object of type 'generator' has no len() 
>>> # We extract each item out individually. We'll do it manually first. 
... 
>>> filtered_gen.next() 
5 
>>> filtered_gen.next() 
9 
>>> filtered_gen.next() 
6 
>>> filtered_gen.next() # Should be all out of items and give an error 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> # Yup, the generator is spent. No values for you! 
... 
>>> # Let's prove it gives the same results as our list comprehension 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> gen_to_list = list(filtered_gen) 
>>> print gen_to_list 
[5, 9, 6] 
>>> filtered_list == gen_to_list 
True 
>>> 

因爲發生器表達式一次只能產生一個項目,所以會導致內存使用量大大節省。生成器表達式最適用於需要一次取一個項目的場景,根據該項目進行大量計算,然後轉到下一個項目。如果您需要多個值,則還可以使用生成器表達式並一次抓取幾個值。如果您在程序開始之前需要所有的值,請改爲使用列表理解。

12

發電機理解是一個列表理解的懶惰版本。

它就像除了它即具有next()方法,將產生下一個元素的對象返回迭代代替列表中的一個列表中理解。

如果你不熟悉列表推導看到here和發電機見​​。

4

列表/發電機理解是一個結構,它可用於從現有的創建一個新的列表/發電機。

比方說,你要生成從1到10每個數字的平方列表您可以在Python做到這一點:

>>> [x**2 for x in range(1,11)] 
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 

這裏,range(1,11)生成列表[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],但range功能不Python 3.0之前的生成器,因此我使用的構造是列表理解。

如果我想創建一個發電機,做同樣的事情,我可以做這樣的:

>>> (x**2 for x in xrange(1,11)) 
<generator object at 0x7f0a79273488> 

在Python 3,但是,range是發電機,所以勝負只取決於語法你使用(方括號或圓括號)。

+1

這是錯誤的。外部表達是否是生成器與內部表達是否無關。顯然,從列表中獲取元素的生成器表達式通常沒有多少意義,您可以這樣做。 – Antimony 2013-03-05 23:46:37

2

發生器理解爲具有一定的結構中產生的發電機的簡單方法。假設你想要一個generator,它可以逐個輸出your_list中的所有偶數。如果使用該函數的風格創建它,它會是這樣:當你調用next(evens)

evens = (number for number in your_list if number % 2 == 0) 

在這兩種情況下,:

def allEvens(L): 
    for number in L: 
     if number % 2 is 0: 
      yield number 

evens = allEvens(yourList) 

你可以實現與這臺發電機理解表達相同的結果獲得your_list中的下一個偶數。

0

發電機的理解是創造iterables,像這對移動資源的光標的方法。如果您知道mysql遊標或mongodb遊標,您可能會意識到整個實際數據不會一次加載到內存中,而是一次加載一次。你的光標來回移動,但內存中總是有一行/列表元素。

總之,通過使用生成器理解,你可以很容易地在python中創建光標。

0

發電機理解的又如:

print 'Generator comprehensions' 

def sq_num(n): 
    for num in (x**2 for x in range(n)):  
     yield num 

for x in sq_num(10): 
    print x