Сопрограммы в Python
Генераторы
Любой более-менее приличный програмист на Python значет, что есть в питоне такая замечательная штука, как функции-генераторы. Главная их особенность – это сохранение состояния между вызовами.
Напомню, как это выглядит.
Возьмём вот такую функцию:
1 2 3 4 5 6 7 |
|
Эта функция принимает на вход имя файла и возвращает его строчка за строчкой, не загружая целиком в память, что может быть необходимо при чтении больших файлов.
Такой приём называют ленивым (lazy) чтением, подразумевая, что мы не делаем работу без необходимости.
Получаем генератор:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Естественно, чаще мы читаем значения из генератора в цикле, а не построчно:
1 2 3 4 5 |
|
Возможна короткая записть генератора:
1 2 3 4 5 6 7 8 9 10 11 |
|
Соответственно нам не надо загружать в память весь список range(0, 100*10000)
, возвращаемое значение “вычисляется” каждый раз при обращении.
Внимание, это не то же самое что списковые выражения!
Они возвращают весь список целиком сразу.
1 2 3 4 |
|
Сопрограммы как частный случай генераторов
А теперь о том, ради чего это, собственно, затевалось. Оказывается, генератор может не только возвращать значения, но и принимать их на вход.
О стандарте можно почитать тут PEP 342.
Предлагаю сразу начать с примера. Напишем простую реализацию генератора, который может складывать два аргумента и хранить историю результатов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Т.е. мы создали генератор, проинициализировали его и подаём ему входные данные.
Он, в свою очередь, эти данные обрабатывает и сохраняет своё состояние между вызовами до тех пор пока мы его не закрыли. После каждого вызова генератор возвращает управление туда, откуда его вызвали.
Тут бы следовало что-то рассказать о конечных автоматах, но, вероятно, я попробую написать об этом отдельно.
Так, с тем, как это работает, вроде, разобрались.
Давайте теперь избавим себя от необходимости каждый раз руками инициализировать генератор.
Сделать это можно примерно так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Тут всё понятно, я думаю.
Сопрограммы могут быть очень полезным инструментом в вашем арсенале разработчика, поскольку они достаточно наглядны, и при этом создание фунций более дешёвая операция по сравнению с созданием объекта класса.
Да и определённый академический интерес они представляют, как мне кажется.
Вот такая вот первая статья.
Опечатки, ошибки, замечания и пожелания можно присылать на shoonoise@gmal.com