60

我们不能在 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

谢谢。

4

4 回答 4

39

因为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(或压缩):

from itertools import izip
k1, k2 = izip(*gen())
于 2013-05-31T11:30:42.400 回答
35

从您给出的示例来看,您的函数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
于 2013-05-31T11:31:00.960 回答
17

采用yield from

def gen():
    for i in range(5):
        yield from (i, i+1)

[v for v in gen()]
# [0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

python 文档说:

使用时yield from <expr>,它将提供的表达式视为子迭代器。

于 2020-01-27T15:39:12.580 回答
0

如果您想从生成器返回多个值,这两种解决方案都可以正常工作。

 def gen():
    for i in range(5):
        yield i, i+1

解决方案1:

 for values in gen():
     print(values[0],values[1])

解决方案2:

 for value1, value2 in gen():
     print(value1, value2)
于 2021-08-15T06:29:35.393 回答