嵌套列表推导式

5

我试图在内部列表推导式中使用外部列表推导式的值:

[ x for x in range(y) for y in range(3) ]

但不幸的是,这会引发一个NameError,因为名称y是未知的(尽管外部列表推导式指定了它)。

这是Python(2.7.3和3.2.3尝试过)的限制还是有很好的原因不能工作?

是否有计划消除这种限制?

是否有解决方法(可能是我没有想到的一些不同语法),以实现我想要的结果?


2
记住顺序的好方法是考虑如果没有列表推导式该怎么做(最近有人提到过这个,印象很深)。 - Levon
3个回答

17

你说的是列表解析,而不是生成器表达式。

你需要交换你的for循环:

[ x for y in range(3) for x in range(y) ]

你需要将它们视为嵌套在普通循环中:

for y in range(3):
    for x in range(y):
        x

多个循环的列表推导式遵循相同的顺序。请参见列表推导式文档:

当提供一个列表推导式时,它由一个表达式和至少一个for子句和零个或多个forif子句组成。在这种情况下,新列表的元素是通过将每个forif子句视为一个块,从左到右嵌套,并评估表达式以在达到最内层块时每次生成一个列表元素而产生的。

生成器表达式也是同样的规则,但使用()括号而不是方括号,并且不会立即生成。

>>> (x for y in range(3) for x in range(y))
<generator object <genexpr> at 0x100b50410>
>>> [x for y in range(3) for x in range(y)]
[0, 0, 1]

1
+1 感谢Martijn,直到现在我才明白顺序。可能与那个“除非你是荷兰人否则不明显”的事情有关。 - Daniel Roseman
1
我必须记住,在迭代时,它将是 for A: for B: C,但在推导中不是(正如我所预期的那样)C for B for A,而是 C for A for B。这很奇怪,我想即使你是荷兰人也一样;-) - Alfe
@Alfe:我注意到PEP是由巴里·沃萨写的,他是一位出色的低音吉他手和全能美国人,而不是吉多。:-P 尽管所有原始工作都是由格雷格·尤因完成的。他是新西兰人。也许这就是原因。 - Martijn Pieters

1

你试过了吗:

[x for y in range(3) for x in range(y)]

因为这会产生一个输出... 这会产生:

[0, 0, 1]

这可能是你想要的,也可能不是...


这正是我想要的,是的。当然,我的用例有点更加复杂。 - Alfe
返回 [ value for target in targetSet for topic, value in self.db[target].keys() if topic == chosenTopic ] - Alfe
1
@Levon,有时会同时发布答案。当我提交后,我发现其他人比我更快。然后我决定添加运行结果,因为其他人还没有包括那个(但我还没有检查)。 - Daren Thomas
实际上它只变成了这样:list(set(value for target in targetSet for topic, values in self.db[target].iteritems() if topic == chosenTopic for value in values if (topic, value) not in trail))。我想知道是否有人能猜到我现在在做什么;-) - Alfe
还有一件事:set([ topic for target in targetSet for topic, values in self.db[target].iteritems() if set((topic, value) for value in values) - trail ])。但现在我离题了,抱歉。 - Alfe

0

只需嵌套另一个生成器。

[ x for x in [range(y) for y in range(3) ]]

给我:

[[], [0], [0, 1]]

但是列表的列表不是我所需要的。不管怎样,谢谢。 - Alfe
@Alfe,你的问题不是很清楚。那就采用Martijn的答案吧。 :) - Inbar Rose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接