Причина в том, что во время создания генератор (a for b in c if d)
оценивает только c
(что иногда делает также предсказуемым b
).Но a
, b
, d
оцениваются во время потребления (на каждой итерации).Здесь при оценке d
(array.count(x) > 0
).
можно использовать текущую привязку array
из охватывающей области. Например, можно выполнить:
g = (x for x in [] if a)
Не объявив a
заранее.Но вы должны убедиться, что a
существует, когда генератор потребляется.
Но вы не можете сделать аналогичным образом:
g = (x for x in a if True)
По запросу:
Вы можете наблюдатьаналогичные (но не идентичные) шаблоны с общей функцией генератора:
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]
Функция генератора не выполняет ни одного из своих элементов до потребления.Следовательно, даже array
в заголовке цикла for связывается поздно.Еще более тревожный пример возникает, когда мы «выключаем» 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