2013-05-31 46 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 ]' –