生成器表达式使用生成器创建后分配的列表 [英] Generator expression uses list assigned after the generator's creation
问题描述
我找到了这个例子,但我不明白为什么它无法正常工作?
我以为它必须输出[1, 8, 15]
或[2, 8, 22]
.
I found this example and I can't understand why it works unpredictably?
I supposed it must output [1, 8, 15]
or [2, 8, 22]
.
array = [1, 8, 15]
g = (x for x in array if array.count(x) > 0)
array = [2, 8, 22]
print(list(g))
>>>[8]
推荐答案
原因是,在创建时,生成器(a for b in c if d)
仅评估c
(有时有时使b
以及可预测的).但是a
,b
,d
是在消耗时间(每次迭代)进行评估的.在这里,当评估d
(array.count(x) > 0
)时,它将使用封闭范围中的array
的 current 绑定.
The reason is that, at creation time, the generator (a for b in c if d)
only evaluates c
(which sometimes makes b
predictable as well). But a
, b
, d
are evaluated at consumption time (at each iteration). Here, it uses the current binding of array
from the enclosing scope when evaluating d
(array.count(x) > 0
).
例如,您可以这样做:
g = (x for x in [] if a)
没有事先声明a
.但是,必须确保在消耗生成器时a
存在.
Without having declared a
in advance. But, you have to make sure a
exists when the generator is consumed.
但是您不能做类似的事情:
But you cannot do similarly:
g = (x for x in a if True)
根据要求:
您可以使用常见的生成器功能观察相似(但不完全相同)的模式:
You can observe similar (however not identical) patterns with a common generator function:
def yielder():
for x in array:
if array.count(x) > 0:
yield x
array = [1, 8, 15]
y = yielder()
array = [2, 8, 22]
list(y)
# [2, 8, 22]
生成器函数在消耗之前不会执行其任何主体.因此,即使for循环标头中的array
也绑定得较晚.甚至还有一个更令人不安的示例,其中我们在迭代过程中退出" array
:
The generator function does not execute any of its body ahead of consumption. Hence, even the array
in the for-loop header is bound late. An even more disturbing example occurs where we "switch out" array
during iteration:
array = [1, 8, 15]
y = yielder()
next(y)
# 1
array = [3, 7]
next(y) # still iterating [1, 8, 15], but evaluating condition on [3, 7]
# StopIteration raised
这篇关于生成器表达式使用生成器创建后分配的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!