Coroutine это класс по своей природе? - PullRequest
0 голосов
/ 03 ноября 2018

Я следую инструкции по изучению сопрограммы

def grep(pattern):
    print("Looking for %s" % pattern)  # prime it(explain shortly)
    while True:
        line = (yield) # expression
        if pattern in line:
            print(line)

Проверьте это

>>> g = grep("python")
>>> g.next()
Looking for python
>>> g.send("coroutine test")
>>> g.send("learning python")

Кажется, что выражение yield работает как functools.partial, за исключением того, что оно должно быть заполнено с помощью next ()

на данный момент, def grep на самом деле class grep, потому что он в первую очередь инициирует объект генератора.

Сложно следовать сопрограмме, насколько я понимаю правильное направление, чтобы продолжить без дальнейших побочных эффектов, поскольку python назвал его def, а не class, должен иметь свои причины.

1 Ответ

0 голосов
/ 03 ноября 2018

Кажется, что выражение yield работает как functools.partial, [за исключением того], что оно должно быть заполнено с использованием next().

Я не уверен, что именно заставляет вас так говорить, но я не сразу вижу параллели. functools.parital предназначен для точного связывания некоторых args / kwargs с вызываемым и позволяет вам сохранять некоторые другие args / kwargs для вызова пользователем. («partial() используется для частичного применения функции, которое« замораживает »некоторую часть аргументов и / или ключевых слов функции, что приводит к созданию нового объекта с упрощенной подписью».) Это не совсем то, что происходит с этим генератором или любым другим генератор.

Сложно следовать сопрограмме, насколько я понимаю правильное направление, чтобы продолжить без дальнейших побочных эффектов, так как Python назвал его def вместо class?

Они хитры, согласны с вами там. Но я не уверен, вижу ли я, что сопрограмма "похожа на класс по своей природе". Сопрограмма - это специализированный генератор. Генераторы определены с def и могут приостанавливать и возобновлять их выполнение. Это описывает генераторы, а не классы, и просто замена def на class была бы синтаксически недействительной, для начала.

Одним из способов выражения любого выражения, например a = yield b, является обозначение точки останова.

Когда вы звоните next(g), он продвигается, пока не достигнет оператора yield, и остановится на этом. Он поместит полученное значение в стек вызовов , но приостановит его выполнение и остановится там, будучи возобновляемым, когда вы снова вызовете next() для него. (Это ключевое различие между функциями и генераторами и между функциями и сопрограммами по расширению.)

При первом вызове next(), line равен None. (В основном, line = yield None.) Вы не сможете повторить это, потому что не можете сказать for pattern in None. Что означает «заправка» в этом случае, вероятно, относится к тому факту, что первоначальный вызов next(g) аналогичен g.send(None).

Теперь, когда вы отправляете дополнительные значения в генератор, они будут назначены на line, тогда как pattern остается «питоном». Если "питон" найден во всем, что вы .send(), он печатается.

>>> g = grep("python")
>>> n = g.send(None)  # equiv to next(g); stop at line = (yield)
Looking for python
>>> n is None
True
>>> g.send("coroutine test")
>>> g.send("coroutine test")
>>> g.send("coroutine test")  # no match
>>> g.send("learning python") # match
learning python
>>> g.send("python3.7") # match
python3.7
...