【发布时间】:2018-05-02 07:30:26
【问题描述】:
下面的例子定义了一个协程multiply,它等待一个值,将它乘以一个常数因子,然后打印结果。另一个函数product_table 使用multiply 生成产品表。
def multiply(factor):
print(f"product table for {factor}")
while True:
sent_value = yield
result = factor * sent_value
print(f"{factor} x {sent_value} = {result}")
def product_table(coro):
coro.send(None) # start coroutine
for value in range(1, 11):
coro.send(value)
product_table(multiply(3))
运行示例产生:
product table for 3
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27
3 x 10 = 30
我试图在async def 和await 方面实现完全相同的示例,但我无处可去。我最初的错误期望是,使用await 的以下协程函数等同于依赖yield 的协程:
async def multiply(factor):
print(f"product table for {factor}")
while True:
await sent_value
result = factor * sent_value
print(f"{factor} x {sent_value} = {result}")
我认为这可能听起来很愚蠢,但对于我迟钝的大脑来说,它显示为“等待发送的值”。事实并非如此——我得到NameError: name 'sent_value' is not defined。
到目前为止,我有限的理解是您可以根据yield(如第一个工作示例),或根据async def和await定义协程函数,正如我在第二个示例中所尝试的那样。好像不是这样的。
我的具体问题是:
- 根据
async def,您将如何实现第一个示例? - 用
async def来实现是否有意义?
我讨厌我发现的所有怪异示例都是在 fake 管道方面到处使用time.sleep(0.1)。我正在尝试撰写一篇博客文章,其中包含使用更具体(如果也是微不足道的)管道的示例。
[删除错误编辑]
【问题讨论】:
-
async def最初是作为语法糖,是的,是为了更容易发现你有一个协程(因为def functionname()不会传达身体某处有yield或 @ 987654342@)。我把它放在 cmets 中是因为你的那部分问题与你的实际问题相切,并且使你的问题边界过于宽泛。我会把它拿出来。 -
您在编辑中实现的内容不起作用:TypeError: object range can't be used in 'await' expression。
range()对象不是可等待的。 -
射击 --- 我运行了错误的文件...正在编辑...
-
具体示例:构建一个 Web 服务,将来自不同来源的信息聚合起来,然后将它们排列在一个列表中。假设你有一堆 REST API 要调用,一些数据库,一些文件数据要处理,然后聚合所有这些并在这些上运行一些排名,最后对结果进行排序。这是可等待对象的绝佳用例,因为您可以等待数据并行出现。这基本上就是 Facebook 和 Instagram 新闻提要的工作方式..
-
请参阅 github.com/Instagram/django-workload/blob/master/… 了解此类设置的超级简化实现。
标签: python async-await python-asyncio coroutine