Coroutine это класс по своей природе?
Я следую инструкции по изучению сопрограмм
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 ответ
Кажется, что выражение 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