2013-05-31 44 views
21

我們不能在python生成器函數中產生多個值嗎?產生多個值

例,

In [677]: def gen(): 
    .....:  for i in range(5): 
    .....:   yield i, i+1 
    .....:   

In [680]: k1, k2 = gen() 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-680-b21f6543a7e9> in <module>() 
----> 1 k1, k2 = a() 

ValueError: too many values to unpack 

這種工作方式如下:即使

In [678]: b = a() 

In [679]: list(b) 
Out[679]: [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] 

同樣的結果時,我這樣做:

In [692]: def a(): 
    for i in range(5): 
     yield i 
     yield i+1 

感謝。

回答

24

因爲gen()回報發生器(單個項目 - 所以它不能被解壓爲兩個),它需要先進的第一得到的值...

g = gen() 
a, b = next(g) 

它與list,因爲這隱含地消耗了生成器。

我們可以進一步使這個發電機?事情是這樣的:

g = gen(); 
def yield_g(): 
    yield g.next(); 
    k1,k2 = yield_g(); 

,因此list(k1)會給[0,1,2,3,4]list(k2)會給[1,2,3,4,5]

保留現有的發電機,並使用izip(或zip):

from itertools import izip 
k1, k2 = izip(*gen()) 
12

你的函數返回gen發電機和沒有價值,你可能期望從你給的例子來看。如果您遍歷發生器值對將產生:

In [2]: def gen(): 
    ...:  for i in range(5): 
    ...:   yield i, i+1 
    ...:   

In [3]: for k1, k2 in gen(): 
    ...:  print k1, k2 
    ...:  
0 1 
1 2 
2 3 
3 4 
4 5 
+0

這不是它。見Jon Clements的答案。 – Marcin

+2

那麼,我的例子是類似的,因爲它使用'for'-循環推進發生器。我同意喬恩的答案更加詳盡,並且更好地解釋發生了什麼問題。儘管如此,我仍然不明白我的回答中的倒退。 –

+0

我們可以進一步使這個發電機?像這樣的東西 'g = gen(); def yield_g():產生g.next(); k1,k2 = yield_g();'因此'list(k1)'會給出'[0,1,2,3,4]'和'list(k2)''[1,2,3,4,5 ]' –