我正在按照指令学习协程
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
应该有她的原因。
答案 0 :(得分:3)
似乎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
仍然是“ 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