生成器表达式使用生成器生成后分配的列表

Gvy*_*tyk 18 python expression generator

我找到了这个例子,我无法理解为什么它无法预测?我认为它必须输出[1, 8, 15][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]
Run Code Online (Sandbox Code Playgroud)

sch*_*ggl 18

原因是,在创建时,生成器(a for b in c if d)仅进行评估c(有时也可以进行b预测).但是a,b,d在消费时间(每次迭代)进行评估.这里,它在evaluate ()时使用封闭范围的当前绑定.arraydarray.count(x) > 0

你可以做:

g = (x for x in [] if a)
Run Code Online (Sandbox Code Playgroud)

没有a事先声明.但是,您必须确保a在生成器被消耗时存在.

但你不能做同样的事情:

g = (x for x in a if True)
Run Code Online (Sandbox Code Playgroud)

根据要求:

您可以使用常见的生成器函数观察相似(但不相同)的模式:

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]
Run Code Online (Sandbox Code Playgroud)

生成器函数在消耗之前不执行任何正文.因此,即使array在for-loop头中也是迟到的.一个更令人不安的例子发生在我们array在迭代期间"切换"的地方:

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
Run Code Online (Sandbox Code Playgroud)


Eug*_*ash 6

Generator表达式的文档:

当为生成器对象调用该方法时,与生成器表达式中使用的变量会被懒惰地评估__next__()(与普通生成器一样).但是,for立即计算最左边子句中的可迭代表达式,以便在定义生成器表达式的位置发出由它产生的错误,而不是在检索第一个值的位置发出.

所以当你跑步

array = [1, 8, 15]
g = (x for x in array if array.count(x) > 0)
Run Code Online (Sandbox Code Playgroud)

array评估生成器表达式中的第一个.x并且array.count(x)只会在您致电时进行评估next(g).由于使用生成器之前array指向另一个列表[2, 8, 22] ,因此会得到"意外"结果.

array = [2, 8, 22]
print(list(g))  # [8]
Run Code Online (Sandbox Code Playgroud)