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
Другие вопросы по тегам