Python 协同程序本质上是一个类?

Python 协同程序本质上是一个类?,python,generator,coroutine,Python,Generator,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") >>

我正在按照指示学习协同程序

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")
屈服表达式似乎作为functools.partial执行,但不包括应该使用next()初始化它

此时,
def grep
实际上是一个
类grep
,因为它首先启动一个生成器对象

协同程序很难遵循,因为python将其命名为
def
而不是
class
应该有她的理由,所以我认为它应该朝着正确的方向继续,而不会产生进一步的副作用

屈服表达式似乎是作为
functools.partial执行的,[除了]它应该使用
next()
进行初始化

我不确定是什么让你这么说,但我并没有立即看到相似之处
functools.parital
设计用于将一些arg/kwarg与可调用对象进行并行绑定,并允许您保存一些其他arg/kwarg以供用户调用。(“
partial()
用于“冻结”函数的某些参数和/或关键字,从而生成具有简化签名的新对象的部分函数应用程序。”)这不是此生成器或任何生成器的实际情况

协同程序很难遵循,因为Python将其命名为
def
,而不是
class
,所以我的理解是否正确,可以继续下去而不会产生进一步的副作用

他们很狡猾,同意你的看法。但我不确定我是否看到了协同程序是如何“本质上像一个类”的。协同程序是一个专门的生成器。生成器使用
def
定义,能够暂停和恢复其执行。这描述的是生成器,而不是类,对于初学者来说,仅仅用
class
替换
def
在语法上是无效的

您可以想到任何表达式,如
a=yield b
的一种方法是标记一个断点。

当您调用
next(g)
时,它将前进,直到遇到
yield
语句,并在那里停止。它会将结果值推送到调用堆栈,但它会暂停执行并在那里停止,当您再次对其调用
next()
时,它是可恢复的。(这是函数和生成器之间以及函数和协同程序之间的关键区别。)

第一次调用
next()
line
None
。(基本上,
line=yield None
)您将无法对其进行迭代,因为您不能在None
中为模式指定
。在这种情况下,“启动”的意思可能是指对
next(g)
的初始调用类似于
g.send(None)

现在,当您将附加值发送到生成器中时,它们将被分配到
,而
模式
保持为“python”。如果在
.send()
中的任何内容中找到“python”,则会将其打印出来

>>> 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

type(grep)
is
function
type(grep('foo'))
is
generator
。我不确定您看到的
functools.partial
的并行性是什么。我猜在其实现细节中它是一个类。但命名为函数时考虑了语法@timgeb@Sawajin你不是在问实施细节吗
grep
function
的一个实例,
grep('foo')
generator
的一个实例。如果它们是类,它们将是
类型的实例(或某些元类)。对于其他读者来说:这个问题似乎源于David Beazley的(见幻灯片)“在这种情况下,“启动”的意思可能是指对next(g)的初始调用类似于g.send(None)。”这一见解让我大开眼界。谢谢。我认为这类似于一个partial,因为,g=grep(“python”)冻结了
python
就像g=functools.partial(grep,“python”),如果grep被定义为一个标准函数。好吧,我有点明白你的意思-但它实际上不需要“冻结”,因为
grep()
实际上只被调用一次。之后,它完全停留在
中,而True
循环和
模式保持不变。这适用于以这种方式定义的任何函数。