[英]appending generators to a stack in loop, generators point to final loop variable
我正在做一些圖遍歷。 在每個點上,我保存了一個可以探索的其他可能選項的生成器。 后來,我探索了一些這些生成器,但它不起作用。
這是一個簡化的示例,您可以在其中看到所有生成器中的“node”變量都設置為3。 (因此生成器指向“node”變量,但“node”變量在生成器消耗之前發生變化。
在我的特定情況下,我可以存儲一些指針並添加如何處理這些指針以重新創建生成器的邏輯 - 但這是一個丑陋的解決方案。
有一個簡單的方法嗎?
node_size = {1:1, 2:2, 3:1, 4:3}
iters = []
for node in range(1,4):
it = (1 + node_size[node]+j for j in xrange(3))
#it = iter(list(it)) #remove comment to get correct result but very slow.
iters.append(it)
for iter_ in iters:
print list(iter_)
"""
Correct Output
[2, 3, 4]
[3, 4, 5]
[2, 3, 4]
"""
"""
Actual Output:
[2, 3, 4]
[2, 3, 4]
[2, 3, 4]
"""
您的生成器表達式引用全局變量node
。 由於這是genexp中的一個自由變量,因此它會關閉名稱 ,而不是值。 在每次從發電機抓住一個項時,表達式1 + node_size[node]+j
與當前值來評價node
。 也就是說,每次生成器前進時都會讀取node
的值,而不是一次創建node
的值。 當您開始從生成器中獲取項目時, node
為3,因此生成器中的所有項都反映該值。
要獲得所需的內容,需要在生成器函數本身中綁定node
。 一個快速的方法是強制node
進入genexp的循環部分:
it = (1 + node_size[node]+j for node in [node] for j in xrange(3))
由於在創建genexp時僅對環路部分進行一次求值,因此這將修復genexp范圍內的單個node
值。
如果這種方式太難看了你,你將不得不編寫一個顯式的生成器函數而不是使用genexp:
def gen(nodeVal):
for j in xrange(3):
yield 1 + node_size[nodeVal]+j
for node in range(1, 4):
iters.append(gen(node))
這里的生成器關閉名稱nodeVal
,但由於每個生成器都是由一個單獨的函數調用創建的,因此每個生成器都有自己的nodeVal
值,一切都很好。
如何使生成器函數接近節點大小值?
node_size = {1:1, 2:2, 3:1, 4:3}
iters = []
for node in xrange(1, 4):
def it(n=node_size[node]):
for j in xrange(1, 4):
yield n + j
itr = it()
iters.append(itr)
for iter_ in iters:
print list(iter_)
這會為我打印出正確的結果。
編輯:@BrenBarn發布了一個答案,直接導致我這個答案:
node_size = {1:1, 2:2, 3:1, 4:3}
iters = []
for node in range(1, 4):
n = node_size[node]
itr = xrange(n+1, n+4)
iters.append(itr)
for iter_ in iters:
print list(iter_)
當你調用xrange()
它會計算它的參數,然后它會返回一個產生數字的迭代器。
我認為在Python中沒有更有效的方法可以做到這一點!
在這種情況下,我們能夠避免所有數學並獲得xrange()
以准確地產生所需的數字。 如果您確實需要評估表達式,您仍然可以使用生成器表達式方式:
itr = (1+j for j in xrange(n, n+3))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.