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)
isfunction
,type(grep('foo'))
isgenerator
。我不确定您看到的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
循环和模式保持不变。这适用于以这种方式定义的任何函数。