2013-04-11 31 views
3

我在做一些圖遍歷。在每一點上,我都會保存一個可能已經探索的其他可能選項的生成器。後來,我探索了一些這樣的生成器,但它不起作用。將生成器附加到循環中的堆棧,生成器指向最終循環變量

這是一個簡化的例子,您可以看到所有生成器中的「節點」變量設置爲3。 (所以發生器指向「節點」變量,但「節點」變量在發生器被消耗之前發生變化。

在我的特殊情況下,我可以存儲一些指針並添加如何處理這些指針的邏輯重新創建發電機 - 但是這是一個醜陋的解決方案

有沒有一種簡單的方法來做到這一點

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] 
""" 
+0

我現在最好的解決方法是使用itertools.repeat – 2013-04-11 03:45:11

回答

6

你發生器表達式引用全局變量node。由於這是genexp中的一個自由變量,因此它將關閉名稱,而不是該值。每當您從發生器中抓取物品時,1 + node_size[node]+j的表達式將以當前的的值爲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,一切都很好。

+0

它的工作:探索=((s - E,e,v)爲pos,E,c在[(pos,E,children)] for s,e, v in(c [i] for i in xrange(pos,len(c)))) – 2013-04-11 04:25:07

1

如何使該收,較節點大小值發生器功能

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))