如何从生成器中获取元组?最佳实践

How to get a tuple out of a generator? Best Practice

我是一名新手程序员,我想创建一个生成器,它将 return 我将在另一个函数中用作元组的两个值。

我不明白为什么 tuple(function_1(a,b)) returns ((1, 2),)tuple(function_2(a,b)) 会 return 一个正确的元组。

我想知道这里发生了什么,什么是最好的语法,并最终知道是否可以从 function_1 中检索元组。

提前感谢您的任何解释!

>>> def function_1(a,b):
...     yield a,b
...
>>> def function_2(a,b):
...     yield a
...     yield b
...
>>> a = 1
>>> b = 2
>>>
>>> function_1(a,b)
<generator object function_1 at 0x1007931b0>
>>> function_2(a,b)
<generator object function_2 at 0x1007931f8>
>>> tuple(function_1(a,b))
((1, 2),)
>>> tuple(function_2(a,b))
(1, 2)
>>> for item in function_1(a,b):
...    print(item)
...
(1, 2)
>>> for item in function_2(a,b):
...    print(item)
...
1
2

第一个函数生成一个元组,第二个函数生成两个单独的值。在 Python 中,每个逗号分隔的列表都是一个元组,括号不是必需的。所以为了说清楚,可以把第一个函数写成

def function_1(a,b):
    yield (a,b)

如果你不喜欢有一个元组,你必须产生两个值,就像在第二个函数中一样。没有别的办法了。

您的第一个生成器只生成 一次,并生成一个元组:

>>> gen = function_1(1, 2)
>>> gen = function_1(1, 2)
>>> next(gen)
(1, 2)
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

如果可用,next() function 从迭代器(生成器是一种特定类型的迭代器)获取下一个值。 StopIteration 异常显示生成器已完成,无法生成更多值。

你的第二个生成器产生 两次不同的时间,每次都是一个整数:

>>> gen = function_2(1, 2)
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

在生成器上调用 tuple() 将引入生成器生成的 所有 值,因此对于 function_1 你将得到一个包含一个元素的元组,另一个元组。对于第二个生成器,您将得到一个包含两个元素的元组,即两个整数。将其与在两个生成器上使用 list() 进行比较:

>>> list(function_1(1, 2))
[(1, 2)]
>>> list(function_2(1, 2))
[1, 2]

现在我们有两个列表,但第一个只包含 一个 元素,一个元组,因为这是生成器生成的全部内容。

因此,这两个生成器具有根本不同的行为。选择你需要的行为;要么产生完整的元组,要么产生单独的值,但不要尝试将两种类型的输出视为同一事物。

>>> tuple((1,2))
(1, 2)

但是在你的情况下 tuple 认为你想要创建一个包含生成器中所有值的元组。

>>> tuple(i for i in [(1, 2)])
((1, 2),)

如果您只想return两个值不要使用生成器。生成器用于 return 一次不需要全部的任意数量的值。