все Python 3Итераторы и генераторыпонятие
Generator function — yield
генераторы
Функция с yield — генераторная функция. Возвращает генератор. Выполнение приостанавливается при yield.
Синтаксис
def gen():
yield value
Вызов генераторной функции не выполняет ни одной строки её тела — только создаёт объект-генератор; код стартует при первом next() или на первой итерации цикла. Генератор одноразовый: после того как он исчерпан, повторный for по той же переменной молча даст ноль итераций — это ловушка, когда результат хотят обойти дважды или сначала посчитать len(). Смысл конструкции — считать элементы по одному и не держать в памяти весь список, поэтому она уместна для больших или бесконечных последовательностей.
Примеры
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)) # → [] исчерпан
См. также
Открыть в полном глоссарииdocs.python.orgСообщить о неточности