我创建了一个完全类型化的不和谐异步库。 我有一个从 aiohttp get 请求创建对象的方法,如下例所示:
async def get_bans(self):
"""|coro|
Fetches all the bans in the guild.
"""
data = await self._http.get(f"guilds/{self.id}/bans")
for ban_data in data:
yield Ban.from_dict(construct_client_dict(self._client, ban_data))
我想知道这个代码片段的返回类型以及它是否应该是
AsyncGenerator[Ban, None]
或AsyncIterator[Ban, None]
。老实说,我一直在寻找一些信息,我可以找到任何能让我对这个主题有清晰想法的信息。
官方文档将AsyncIterator描述为:
...提供
和__aiter__
方法 ...__anext__
AsyncGenerator 从文档引向PEP525。
...生成器是包含一个或多个
表达式的任何函数...yield
调用异步生成器函数的结果是一个异步生成器对象...
异步生成器定义了这两种方法(
和__aiter__
)__anext__
所以我认为,由于函数中的
yield
,最好使用AsyncGenerator
。
我是从语义的角度来看它。
AsyncGenerator
是AsyncIterator
的继承者。来自 Python 3.12 来源:
class AsyncGenerator(AsyncIterator[_YieldT_co], Generic[_YieldT_co, _SendT_contra]): ...
进行简短检查以确认这一点:
>>> async def gen_or_iter():
... yield 1
...
>>> x = gen_or_iter()
>>> isinstance(x, typing.AsyncGenerator)
True
>>> isinstance(x, typing.AsyncIterator)
True
>>>
在我看来,如果使用
asend()
不适用于具体的生成器实现,换句话说,该函数不使用像 x = yield
这样的表达式,并且表现为纯迭代器,则 AsyncGenerator[T, None]
在语义上与 AsyncIterator[T]
相同.
因此,尽管
AsyncGenerator[T, None]
是一个更精确的声明,但在纯迭代器行为的情况下,使用 AsyncIterator[T]
也可能是正确且合理的。