В Python генератор - это объект, который предназначен для создания последовательностей. С его помощью вы можете итерировать потенциально огромные последовательности, не создавая и не сохраняя всю последовательность в памяти сразу.
Генераторы часто становятся источником данных для итераторов.
В Python 2 функция range() возвращает список, ограниченный так, чтобы он помещался в память. В Python 2 также есть функция xrange(), которая стала обычной функцией range() в Python 3. В этом примере складываются все целые числа от 1 до 100:
>>> sum(range(1, 101))5050
Каждый раз при итерации через генератор, он отслеживает, где находился во время последнего вызова, и возвращает следующее значение. Это отличает его от обычной функции, которая не помнит о предыдущих вызовах и всегда начинает работу с первой строки в том же состоянии.
Функции-генераторы
Можно самому написать функцию-генератор, если нужно создать потенциально большую последовательность. Это будет обычная функция, но возвращать значение будет с помощью выражения yield, а не return:
>>> def my_range(first=0, last=10, step=1): number = first while number < last: yield number number += step# Это обычная функция:>>> my_range<function my_range at 0x10193e268># Возвращает объект генератора:>>> ranger = my_range(1, 5)>>> ranger<generator object my_range at 0x101a0a168>
Можно проитерировать по этому объекту генератора:
>>> for x in ranger: print(x)1234
Генератор можно запустить только один раз
Списки, множества, строки и словари существуют в памяти, а генераторы создают свои значения на лету и выдают их по одному с помощью итератора.
Генератор не запоминает значения, поэтому не получится перезапустить его или создать резервную копию.
>>> for try_again in ranger: print(try_again)>>> # генератор истощился
Включения генераторов (comprehensions)
Заключается в круглые скобки. Оно похоже на сокращенную функцию-генератор, которая неявно выполняет yield и возвращает объект генератора:
>>> genobj = (pair for pair in zip(['a', 'b'], ['1', '2']))>>> genobj<generator object <genexpr> at 0x10308fde0>>>> for thing in genobj: print(thing)('a', '1')('b', '2')
Функции в python
Соус: Книга “Простой Python” → Глава 9. “Функции” → “Генераторы”