为什么重新定义生成器中使用的变量会产生奇怪的结果?

pic*_*ick 31 python generator

我的一个朋友问我这段代码:

array = [1, 8, 15]
gen = (x for x in array if array.count(x) > 0)
array = [2, 8, 22]
print(list(gen))
Run Code Online (Sandbox Code Playgroud)

输出:

[8]
Run Code Online (Sandbox Code Playgroud)

其他元素去哪儿了?

Dan*_*ejo 32

答案就在生成器表达式的 PEP 中,特别是会话Early Binding 与 Late biding

经过多次讨论,决定应立即计算第一个(最外层)for 表达式,并在执行生成器时计算其余表达式。

所以基本上array是:

x for x in array 
Run Code Online (Sandbox Code Playgroud)

使用原始列表[1, 8, 15](即立即)进行评估,而另一个:

if array.count(x) > 0
Run Code Online (Sandbox Code Playgroud)

当使用以下方式执行生成器时进行评估:

print(list(gen))
Run Code Online (Sandbox Code Playgroud)

此时array引用一个新列表[2, 8, 22]

  • @picklerick 不,因为 **for-loop** 表达式是用数组的第一个值来计算的,基本上你的代码相当于 `list(x for x in [1, 8, 15] if [2, 8, 22 ].count(x) > 0)` (5认同)

Fel*_*elk 12

如果为每个数组指定一个唯一的名称而不是重新绑定,这一点会变得更加清晰array

array1 = [1, 8, 15]
gen = (x for x in array1 if array2.count(x) > 0)
array2 = [2, 8, 22]
print(list(gen))
Run Code Online (Sandbox Code Playgroud)

x for x in array1在创建生成器时评估,但if array2.count(x) > 0评估是延迟的,这就是为什么您已经可以引用尚未定义的变量