簡體   English   中英

如何打印生成器表達式?

[英]How to print a generator expression?

在 Python shell 中,如果我輸入一個列表理解,例如:

>>> [x for x in string.letters if x in [y for y in "BigMan on campus"]]

我得到了一個很好的打印結果:

['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']

字典理解也一樣:

>>> {x:x*2 for x in range(1,10)}
{1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}

如果我輸入生成器表達式,我會得到不那么友好的響應:

>>> (x for x in string.letters if x in (y for y in "BigMan on campus"))
<generator object <genexpr> at 0x1004a0be0>

我知道我可以這樣做:

>>> for i in _: print i,
a c g i m n o p s u B M

除此之外(或編寫輔助函數)我可以在交互式 shell 中輕松評估和打印生成器 object 嗎?

快速回答:

在生成器表達式周圍執行list()與(幾乎)完全等效於將[]括號括起來。 所以是的,你可以做到

>>> list((x for x in string.letters if x in (y for y in "BigMan on campus")))

但你也可以這樣做

>>> [x for x in string.letters if x in (y for y in "BigMan on campus")]

是的,這會將生成器表達式轉換為列表推導式。 這是同一件事,並在其上調用 list() 。 所以將生成器表達式變成列表的方法是在它周圍加上括號。

詳細解釋:

發電機表達式是“裸露的” for表達。 像這樣:

x*x for x in range(10)

現在,你不能把它單獨放在一行上,你會得到一個語法錯誤。 但是你可以在它周圍加上括號。

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7485464>

這有時被稱為生成器理解,雖然我認為官方名稱仍然是生成器表達式,但實際上沒有任何區別,括號只是為了使語法有效。 如果將其作為唯一參數傳遞給函數,則不需要它們,例如:

>>> sorted(x*x for x in range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

基本上,Python 3 和 Python 2.7 中可用的所有其他理解都只是圍繞生成器表達式的語法糖。 設置理解:

>>> {x*x for x in range(10)}
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}

>>> set(x*x for x in range(10))
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}

字典理解:

>>> dict((x, x*x) for x in range(10))
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

>>> {x: x*x for x in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

並列出 Python 3 下的推導式:

>>> list(x*x for x in range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

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

在 Python 2 下,列表推導不僅僅是語法糖。 但唯一的區別是 x 在 Python 2 下會泄漏到命名空間中。

>>> x
9

在 Python 3 下你會得到

>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

這意味着在 Python 中獲得生成器表達式內容的漂亮打印輸出的最佳方法是對其進行列表理解! 但是,如果您已經有一個生成器對象,這顯然不起作用。 這樣做只會列出一個生成器:

>>> foo = (x*x for x in range(10))
>>> [foo]
[<generator object <genexpr> at 0xb7559504>]

在這種情況下,您需要調用list()

>>> list(foo)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

雖然這有效,但有點愚蠢:

>>> [x for x in foo]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

與列表或字典不同,生成器可以是無限的。 這樣做是行不通的:

def gen():
    x = 0
    while True:
        yield x
        x += 1
g1 = gen()
list(g1)   # never ends

此外,閱讀生成器會改變它,因此沒有一種完美的方式來查看它。 要查看生成器輸出的示例,您可以執行以下操作

g1 = gen()
[g1.next() for i in range(10)]

您可以將表達式包裝在對list的調用list

>>> list(x for x in string.letters if x in (y for y in "BigMan on campus"))
['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']

或者,您始終可以map迭代器,而無需構建中間列表:

>>> _ = map(sys.stdout.write, (x for x in string.letters if x in (y for y in "BigMan on campus")))
acgimnopsuBM
>>> list(x for x in string.letters if x in (y for y in "BigMan on campus"))
['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']

生成器 object 不存儲實際數據,它基本上只是一個表達式。 程序無法在不評估表達式的情況下打印表達式的值。 生成器對象(生成器表達式)可以通過類型轉換為任何可迭代的數據類型來評估。

例如。

list(genexpr)
dict(genexpr)
set(genexpr)
for data in genexpr: 

額外的

生成生成器表達式然后進行類型轉換比直接創建所需的數據類型 object 慢 20%。 因此,如果我們需要整個數據,最好使用

data=[x for x in range(0,10)]

比使用

genexpr=(x for x in range(0,10))
data=list(genexpr)
print(i for i in range(9))

如果我們運行它,我們將得到 output 為: - <generator object at 0x000001F01A153E40>

打印生成器的一種簡單方法是將其轉換為列表。 所以很簡單,如果我們將代碼修改為print(*[i for i in range(9)])

所以我們將得到 output 為:0 1 2 3 4 5 6 7 8

你也可以這樣做:

gen = (i for i in 'abcde')
print( *gen ) # => a b c d e

暫無
暫無

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

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