Python 嵌套在理解中的生成器的意外行为
在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] 我认为这是因为用于定义生成器的变量
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
!这个例子仅仅是一个玩具例子,从一个更有意义的案例中得到启发,可以轻松地调查这种意外行为