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

Python 嵌套在理解中的生成器的意外行为,python,python-3.x,python-2.7,generator,dictionary-comprehension,Python,Python 3.x,Python 2.7,Generator,Dictionary Comprehension,在Python中,当使用嵌套在理解中的生成器时,我得到了一个意外的行为,在下面这个特定的例子中是字典理解。更具体地,考虑下面的简单理解: D={x:(y表示范围(5)中的y,如果y==x)表示范围(5)中的x} 我希望获得一个字典D,这样list(D[x])==[x]对于从0到4的每个整数I。相反,结果是 列表(D[0]) [4] >>>名单(D[1]) [4] >>>名单(D[2]) [4] >>>名单(D[3]) [4] >>>名单(D[4]) [4] 我认为这是因为用于定义生成器的变量

在Python中,当使用嵌套在理解中的生成器时,我得到了一个意外的行为,在下面这个特定的例子中是字典理解。更具体地,考虑下面的简单理解:

D={x:(y表示范围(5)中的y,如果y==x)表示范围(5)中的x}
我希望获得一个字典
D
,这样
list(D[x])==[x]
对于从0到4的每个整数I。相反,结果是

列表(D[0]) [4] >>>名单(D[1]) [4] >>>名单(D[2]) [4] >>>名单(D[3]) [4] >>>名单(D[4]) [4] 我认为这是因为用于定义生成器的变量
x
的值一直在变化,直到被固定为4为止。但是,我认为每个生成器应该在定义时使用变量的精确值来定义。对于这个简单的嵌套结构,是否有一种正确的替代方法,并且达到预期的效果

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

D={x:list((y表示范围(5)中的y,如果y==x))表示范围(5)中的x}

但我对保留生成器使用的解决方案感兴趣。

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)}

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]表示范围(5)内的x}
打印(d[3](3))
这将提供:

[3]

对于您描述的场景(我不理解您为什么需要内部理解),您可以简单地使用以下内容:

d={x:lambda x:[x]表示范围(5)内的x}
打印(d[3](3))
这将提供:

[3]

每个生成器只产生一个元素;为什么要麻烦?或者你认为所有5把钥匙都会共用一个发电机?这不是
dict
的工作方式。
x
只是生成器内部的一个自由变量;它的值在你实际遍历生成器之前不会被查找。不清楚你为什么需要内在理解?改用
lambda
!该示例只是一个玩具示例,可以轻松地调查这种意外行为,灵感来自一个更有意义的案例,每个生成器只生成一个元素;为什么要麻烦?或者你认为所有5把钥匙都会共用一个发电机?这不是
dict
的工作方式。
x
只是生成器内部的一个自由变量;它的值在你实际遍历生成器之前不会被查找。不清楚你为什么需要内在理解?改用
lambda
!这个例子仅仅是一个玩具例子,从一个更有意义的案例中得到启发,可以轻松地调查这种意外行为