嵌套在理解中的生成器的意外行为

Unexpected behaviour of generator nested in a comprehension

当使用嵌套在推导中的生成器时,我在 Python 中出现意外行为,在下面的特定情况下是字典推导。更具体地说,考虑以下简单的理解:

D = {x : (y for y in range(5) if y==x) for x in range(5)}

我本希望得到一个字典 D 使得每个整数 i 从 0 到 4 都 list(D[x]) == [x]。相反,结果是

>>> list(D[0])
[4]
>>> list(D[1])
[4]
>>> list(D[2])
[4]
>>> list(D[3])
[4]
>>> list(D[4])
[4]

我认为发生这种情况是因为用于定义生成器的变量 x 的值一直在变化 until 被固定为 4。但是,我认为每个生成器都应该使用确切的值来定义定义时的变量。对于这个简单的嵌套结构,是否有替代方法以更正的方式并达到预期的结果?

请注意,将生成器实现为列表会修复此行为:

D = {x : list((y for y in range(5) if y==x)) for x in range(5)}

但我对保留发电机使用的解决方案很感兴趣。

x 是一个自由变量,因此在您实际迭代生成器之前不会考虑它的值。正如您所注意到的,这意味着 x 的值可以在生成器定义和实际使用之间发生变化。

无法将值传递给生成器表达式;你必须使用生成器函数:

def make_generator(x):
    for y in range(5):
        if y == x:
            yield y

D = {x: make_generator(x) for x in range(5)}

对于你所描述的场景(我不明白你为什么需要内悟),你可以简单地使用以下内容:

d = {x:lambda x: [x] for x in range(5)}
print(d[3](3))

这将给出:

[3]