簡體   English   中英

生成器理解究竟是如何工作的?

[英]How exactly does a generator comprehension work?

生成器理解有什么作用? 它是如何工作的? 我找不到關於它的教程。

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

>>> 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 <genexpr> at 0x7f2ad75f89e0>
>>> 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.
... 
>>> next(filtered_gen)
5
>>> next(filtered_gen)
9
>>> next(filtered_gen)
6
>>> next(filtered_gen) # 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
>>> 

因為生成器表達式一次只需要產生一項,所以它可以大大節省內存使用量。 生成器表達式在您需要一次取一個項目,根據該項目進行大量計算,然后繼續下一個項目的情況下最有意義。 如果您需要多個值,您也可以使用生成器表達式並一次抓取幾個。 如果在程序繼續之前需要所有值,請改用列表推導式。

生成器推導式是列表推導式的惰性版本。

它就像一個列表推導式,除了它返回一個迭代器而不是列表,即一個具有 next() 方法的對象,它將產生下一個元素。

如果您不熟悉列表推導式,請參閱此處,對於生成器,請參閱此處

列表/生成器推導式是一種構造,您可以使用它從現有列表/生成器創建新的列表/生成器。

假設您要生成從 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 之前的生成器,因此構造 I 've 使用的是列表理解。

如果我想創建一個做同樣事情的生成器,我可以這樣做:

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

然而,在 Python 3 中, range是一個生成器,因此結果僅取決於您使用的語法(方括號或圓括號)。

生成器理解是創建具有特定結構的生成器的一種簡單方法。 假設您想要一個generator ,它可以一一輸出your_list所有偶數。 如果您使用函數樣式創建它,它將是這樣的:

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

evens = allEvens( yourList )

您可以使用此生成器理解表達式獲得相同的結果:

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

在這兩種情況下,當您調用next(evens)您將獲得your_list的下一個偶數。

生成器理解的另一個例子:

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 

生成器理解是一種創建可迭代對象的方法,類似於在資源上移動的光標。 如果您了解 mysql 游標或 mongodb 游標,您可能知道整個實際數據永遠不會一次加載到內存中,而是一次加載一個。 您的光標來回移動,但內存中始終只有一行/列表元素。

簡而言之,通過使用生成器理解,您可以輕松地在 python 中創建游標。

生成器僅與列表相同,細微的區別是在列表中我們得到所有需要的數字或列表中的項目,但在生成器中,所需的數字一次產生一個。 因此,為了獲取所需的項目,我們必須使用 for 循環來獲取所有所需的項目。

#to get all the even numbers in given range
 
def allevens(n):
    for x in range(2,n):
        if x%2==0:
            yield x

for x in allevens(10)
print(x)

#output
2
4
6
8

我們可以將其理解為列表理解的生成器版本。 在列表理解的情況下,我們創建一個使用單行代碼或短代碼的生成器理解,我們為生成器創建單行代碼或小代碼。 它們具有相同的語法,只是將 [](方括號)替換為 () 大括號。

generator_composition_object = (num**3 for num in range(5))
print(generator_composition_object)

這將給出類型生成器的 object 的地址。 我們還可以在其中使用像 next() 這樣的功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM