2012-10-09 47 views
0

我嘗試使用過字典嵌套發生器理解與列表作爲存儲的值,並觀察到以下怪(我的)行爲:誤區關於嵌套產生理解上的字典

Python 2.6.5 (r265:79063, Oct 1 2012, 22:07:21) 
[GCC 4.4.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> dummy = {1:[1,2,3],2:[2,3,4],3:[3,4,5]} 
>>> a = (d for _,d in dummy.iteritems()) 
>>> a.next() 
[1, 2, 3] 
>>> a.next() 
[2, 3, 4] 
>>> a.next() 
[3, 4, 5] 
>>> a.next() 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
StopIteration 

這是有道理的。接下來沒有(至少對我來說)

>>> aa = (dd for dd in (d for _,d in dummy.iteritems())) 
>>> aa.next() 
[1, 2, 3] 
>>> aa.next() 
[2, 3, 4] 
>>> aa.next() 
[3, 4, 5] 
>>> aa.next() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 

爲什麼我的(未遂)嵌套發生器理解的行爲方式作爲非嵌套的版本一樣嗎?我會期望每個aa.next()都給出一個單獨的元素結果,而不是一個列表。

回答

1

你的內發電機每個是時間返回單個值迭代,每個值都是一個列表。您將需要使用實際的嵌套結構。

>>> aa = (d3 for dd in (d for _,d in dummy.iteritems()) for d3 in dd) 
>>> next(aa) 
1 
>>> next(aa) 
2 
>>> next(aa) 
3 
>>> next(aa) 
2 
>>> next(aa) 
3 
>>> next(aa) 
4 
>>> next(aa) 
3 
>>> next(aa) 
4 
>>> next(aa) 
5 
>>> next(aa) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
0

這不是一個真正的「嵌套」生成器,因爲你正在考慮它。

您的代碼是(大約)等效於:

for dd in (d for _,d in dummy.iteritems()): 
    print dd 

典型地,「嵌套」被用於表示這樣的:

(dd for _, d in dummy.iteritems() for dd in d) 
1

爲了嵌套,你不需要內部發生器。相反,使用純嵌套的循環:

>>> dummy = {1:[1,2,3],2:[2,3,4],3:[3,4,5]} 
>>> aa = (dd for _,d in dummy.iteritems() for dd in d) 
>>> list(aa) 
[1, 2, 3, 2, 3, 4, 3, 4, 5] 

,將做相同:

def aa(dummy): 
    for _, d in dummy.iteritems(): 
     for dd in d: 
      yield dd 

print list(aa()) 

學習發電機表達的最好的辦法是先使用普通的生成器,這樣你可以很容易地看到結果在每一步。