理解:每次迭代多个值

Asa*_*din 10 python list-comprehension generator

有没有办法在列表/字典/集合理解中每次迭代输出两个(或更多)项?作为一个简单的例子,要输出从1到3的整数的所有正和负双精度(也就是说{x | x = ±2n, n ? {1...3}}),是否存在类似于以下的语法?

>>> [2*i, -2*i for i in range(1, 4)]
[2, -2, 4, -4, 6, -6]
Run Code Online (Sandbox Code Playgroud)

我知道我可以输出元组(+i,-i)并将其弄平,但我想知道是否有任何方法可以使用单一理解来完全解决问题.

目前,我正在生成两个列表并将它们连接起来(如果订单不重要,则可以正常工作):

>>> [2*i for i in range(1, 4)] + [-2*i for i in range(1, 4)]
[2, 4, 6, -2, -4, -6]
Run Code Online (Sandbox Code Playgroud)

geo*_*org 8

另一种选择是嵌套理解:

r = [2*i*s for i in range(1, 4) for s in 1, -1]
Run Code Online (Sandbox Code Playgroud)

对于更一般的情况:

r = [item for tpl in (<something that yields tuples>) for item in tpl]
Run Code Online (Sandbox Code Playgroud)

用你原来的例子:

r = [item for tpl in ((2*i, -2*i) for i in range(1, 4)) for item in tpl]
Run Code Online (Sandbox Code Playgroud)

虽然我真的建议itertools.chain.from_iterable@Lattyware说.


daw*_*awg 8

嵌套理解的另一种形式:

>>> [sub for i in range(1, 4) for sub in (2*i, -2*i)]
[2, -2, 4, -4, 6, -6]
Run Code Online (Sandbox Code Playgroud)


Gar*_*tty 6

这里最好的答案是简单地使用itertools.chain.from_iterable(),正如您所提到的,将列表展平:

itertools.chain.from_iterable((2*i, -2*i) for i in range(1, 4))
Run Code Online (Sandbox Code Playgroud)

这是非常易读的,并且不需要对源进行两次迭代(鉴于某些迭代器可能会耗尽,这可能有问题,这意味着额外的计算工作)。

  • 当标准库中存在某些内容时,没有理由重新发明轮子 - 没有理由担心“导入”。`itertools` 是 Python 的重要组成部分(只需查看有多少 SO Python 答案使用它)。它快速、高效,并且可以完成大量工作,因此您无需这样做。 (2认同)

jam*_*lak 6

虽然我会使用itertools@Lattyware 建议的方法,但这里有一个使用生成器的更通用的方法,也可能会有帮助。

>>> def nums():
        for i in range(1, 4):
            yield 2*i
            yield -2*i


>>> list(nums())
[2, -2, 4, -4, 6, -6]
Run Code Online (Sandbox Code Playgroud)