all Python 3Iterators & generatorsterm
Generator function — yield
generators
A function with yield is a generator function. It returns a generator. Execution is suspended at each yield.
Syntax
def gen():
yield value
Calling a generator function runs none of its body — it only builds a generator object; the code starts at the first next() or the first loop iteration. Generators are single-pass: once exhausted, a second for over the same variable silently yields nothing, which bites people who want to iterate twice or take len() first. The whole point is producing items one at a time instead of materialising a list, which is what makes huge or infinite sequences workable.
Examples
def count_up(n):
i = 0
while i < n:
yield i
i += 1
for x in count_up(4):
print(x, end=' ') # → 0 1 2 3
# Бесконечный генератор
def naturals():
n = 1
while True:
yield n
n += 1
from itertools import islice
print(list(islice(naturals(), 5))) # → [1,2,3,4,5]
# Ленивые вычисления
def read_large_file(path):
# Открывает файл ленивно
with open(path) as f:
for line in f:
yield line.strip()
# Сохраняет память!
# Состояние между вызовами
def running_total(lst):
total = 0
for x in lst:
total += x
yield total
print(list(running_total([1,2,3,4]))) # → [1,3,6,10]
# Фибоначчи-генератор
def fib_gen():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
g = fib_gen()
print([next(g) for _ in range(8)]) # → [0,1,1,2,3,5,8,13]
# send() — отправить значение в генератор
def accumulator():
total = 0
while True:
value = yield total
if value is not None:
total += value
acc = accumulator()
next(acc) # инициализация
print(acc.send(10)) # → 10
print(acc.send(5)) # → 15
# Генератор можно обходить только раз
g2 = count_up(3)
print(list(g2)) # → [0,1,2]
print(list(g2)) # → [] исчерпан
See also
Open in the full glossarydocs.python.orgReport an inaccuracy