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")
似乎 yield 表达式作为 functools.partial 执行,不包括它应该使用 next() 启动
此时,def grep
实际上是 a class grep
,因为它首先启动了一个生成器对象。
协程很难遵循,我对正确方向的理解是继续没有进一步的副作用,因为 python 命名它def
而不是class
应该有她的理由。
解决方案
似乎 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
推荐阅读
- ios - 观看视频时录制带音频的视频
- excel - 在 Excel VBA 中搜索和替换通配符
- c++ - basic_istream::seekg() 似乎不起作用
- c++ - 将 unsigned char * 转换为十六进制字符串
- c# - UWP 中的时、分、秒有时间控制吗?
- javascript - 无法使用 ExpressJS 和 CSRF 发布
- java - 在 Java 中将 XML 解组为对象(Apache Camel)
- javascript - 通过 JS 中的 mb_strlen 等字符检查长度
- javascript - 如何使用 Bootstrap 和 thymeleaf 在模态内部的表单中填充值?
- c# - DbContext 解耦