Python 'AsyncIterable[T]`和'Iterable[Waitiable[T]]]之间的区别是什么?
执行以下两个功能:Python 'AsyncIterable[T]`和'Iterable[Waitiable[T]]]之间的区别是什么?,python,asynchronous,async-await,generator,python-asyncio,Python,Asynchronous,Async Await,Generator,Python Asyncio,执行以下两个功能: import asyncio def a(): for index in range(2): # Capture `index` as `local_index` in case awaiting is postponed. async def next_index(local_index=index): # Simulate network request. await asyncio
import asyncio
def a():
for index in range(2):
# Capture `index` as `local_index` in case awaiting is postponed.
async def next_index(local_index=index):
# Simulate network request.
await asyncio.sleep(0)
return local_index
yield next_index()
async def b():
for index in range(2):
# Simulate network request.
await asyncio.sleep(0)
yield index
a
返回一个Iterable[waitiable[int]]
b
返回一个异步可编[int]
。两种方法的迭代都可以这样做:
async def main():
for index in a():
print(await index)
async for index in b():
print(index)
asyncio.run(main())
输出:
0
1
0
1
上面示例中的关键是,我能够在没有外部async
的情况下生成Awaitable
s,因为内部函数是async
AsyncIterable[T]
是否有什么比Iterable[waitiable[T]]
更好的地方异步
来生成可等待的s,那么\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
这可能是我遗漏了一些东西的地方,但从我目前的理解来看,异步协议和
StopAsyncIteration
似乎可以使用同步协议和StopIteration
(当然不那么简洁)来模仿它们。您遗漏的一个大问题是如何处理循环结束
异步迭代器的\uuuu anext\uuuu
返回一个可等待的值,该值可以挂起、使用值提升StopIteration
以生成下一个元素,或者提升StopAsyncIteration
以发出循环结束的信号。(政治公众人物说“要停止迭代,必须引发StopAsyncIteration异常。”,但StopAsyncIteration异常实际上是在等待可等待的对象时发生的,而不是在调用\UuAsyncIteration\UuncE>时同步发生的。)
相反,如果您尝试使用可等待的元素使常规iterable,那么迭代器的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
需要启动停止迭代来结束循环
这意味着,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>在知道是否会有另一个元素之前不能返回<代码>\uuuuuuuuuuuuuuuuuuuuuu下一步\uuuuuuuu
是同步的,所以当它计算出这一点时,控件不能返回到事件循环。这意味着当所有其他工作暂停时,您可能会浪费大量时间同步等待网络流量或其他信息
您可以通过更多的手动处理来解决这个问题,但这在两端都会变得非常棘手,尤其是迭代器端,您需要某种类似于StopAsyncIteration的方法来消除“下一个元素”与“循环完成”之间的歧义