- en
- Language: ru
- Documentation version: latest
25. Корутины¶
Coroutines похожи на генераторы с некоторыми отличиями. Основными отличиями являются:
генераторы являются производителями данных
Корутины являются потребителями данных
Прежде всего, давайте рассмотрим процесс создания генераторов. Мы можем создавать генераторы следующим образом:
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
Затем мы обычно используем его в цикле for
следующим образом:
for i in fib():
print(i)
Она быстра и не оказывает большого давления на память, поскольку генерирует значения на лету, а не хранит их в списке. Теперь, если мы используем yield
в приведенном выше примере, в общем случае мы получим корутину. Корутины потребляют значения, которые им посылаются. Очень простым примером может быть альтернатива grep
в Python:
def grep(pattern):
print("Searching for", pattern)
while True:
line = (yield)
if pattern in line:
print(line)
Подождите! Что возвращает yield
? Ну, мы превратили его в корутину. Изначально она не содержит никаких значений, вместо этого мы предоставляем ей значения извне. Мы предоставляем значения с помощью метода .send()
. Вот пример:
search = grep('coroutine')
next(search)
# Output: Searching for coroutine
search.send("I love you")
search.send("Don't you love me?")
search.send("I love coroutines instead!")
# Output: I love coroutines instead!
Доступ к отправленным значениям осуществляется с помощью yield
. Почему мы запустили next()
? Это необходимо для того, чтобы запустить корутину. Как и generators
, корутины не запускают функцию немедленно. Вместо этого они запускают ее в ответ на методы __next__()
и .send()
. Поэтому необходимо выполнить next()
, чтобы выполнение продвинулось до выражения yield
.
Мы можем закрыть корутину, вызвав метод .close()
:
search = grep('coroutine')
# ...
search.close()
В coroutines
есть еще много интересного. Я предлагаю вам ознакомиться с this awesome presentation Дэвида Бизли.