Skip to content

Генераторы в python

В Python генератор - это объект, который предназначен для создания последовательностей. С его помощью вы можете итерировать потенциально огромные последовательности, не создавая и не сохраняя всю последовательность в памяти сразу.
Генераторы часто становятся источником данных для итераторов.

В Python 2 функция range() возвращает список, ограниченный так, чтобы он помещался в память. В Python 2 также есть функция xrange(), которая стала обычной функцией range() в Python 3. В этом примере складываются все целые числа от 1 до 100:

Python
>>> sum(range(1, 101))
5050

Каждый раз при итерации через генератор, он отслеживает, где находился во время последнего вызова, и возвращает следующее значение. Это отличает его от обычной функции, которая не помнит о предыдущих вызовах и всегда начинает работу с первой строки в том же состоянии.

Функции-генераторы

Можно самому написать функцию-генератор, если нужно создать потенциально большую последовательность. Это будет обычная функция, но возвращать значение будет с помощью выражения yield, а не return:

Python
>>> 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>

Можно проитерировать по этому объекту генератора:

Python
>>> for x in ranger:
        print(x)

1
2
3
4

Генератор можно запустить только один раз

Списки, множества, строки и словари существуют в памяти, а генераторы создают свои значения на лету и выдают их по одному с помощью итератора.
Генератор не запоминает значения, поэтому не получится перезапустить его или создать резервную копию.

Python
>>> for try_again in ranger:
         print(try_again)

>>>  # генератор истощился

Включения генераторов (comprehensions)

Заключается в круглые скобки. Оно похоже на сокращенную функцию-генератор, которая неявно выполняет yield и возвращает объект генератора:

Python
>>> 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. "Функции" --> "Генераторы"

python