如何为异步filter函数实现正确的泛型类型标注?
实现带正确泛型类型标注的异步版
filter函数 完整实现代码
导入必要的类型工具,通过函数重载模仿内置filter的泛型行为,实现类型安全的异步过滤:
from typing import ( AsyncIterator, AsyncGenerator, Callable, TypeGuard, TypeIs, TypeVar, overload, Optional, ) _T = TypeVar("_T") _S = TypeVar("_S") @over**************************************************************** initiating> Regardless的 s(天下 normativeDO负责这里是重载定义,对应不同输入场景) @overload async def afilter( predicate: None, iterable: AsyncIterator[_T | None], /, ) -> AsyncGenerator[_T, None]: ... @overload async def afilter( predicate: Callable[[_S], TypeGuard[_T]], iterable: AsyncIterator[_S], /, ) -> AsyncGenerator[_T, None]: ... @overload async def afilter( predicate: Callable[[_S], TypeIs[_T]], iterable: AsyncIterator[_S], /, ) -> AsyncGenerator[_T, None]: ... @overload async def afilter( predicate: Callable[[_T], bool], iterable: AsyncIterator[_T], /, ) -> AsyncGenerator[_T, None]: ... # 核心实现逻辑 async def afilter( predicate: Optional[Callable[..., bool]], iterable: AsyncIterator, /, ): async for item in iterable: if predicate is None: if item is not None: yield item elif predicate(item): yield item # 测试用例 async def simulated_data() -> AsyncIterator[int | None]: for i in [1, None, 3, 5]: yield i async def test_afilter(): # 类型会被正确推断为 AsyncGenerator[int, None] result = afilter(None, simulated_data()) async for num in result: # 此处num类型明确为int,无None风险 print(num + 1)
解决异步推导式的类型问题
如果想用异步推导式实现,需要用显式的TypeGuard函数辅助类型检查器识别过滤逻辑,替代直接写item is not None:
def is_not_none(x: _T | None) -> TypeGuard[_T]: return x is not None async def test_comprehension(): # 类型会被正确推断为 AsyncGenerator[int, None] filtered = (item async for item in simulated_data() if is_not_none(item)) async for num in filtered: print(num + 1)
关键细节说明
- 函数重载的必要性:模仿内置
filter的泛型设计,通过@overload为不同输入场景指定精确返回类型,让类型检查器能准确推断过滤后的结果类型。 - TypeGuard的作用:直接在推导式中写
item is not None时,部分类型检查器无法自动识别为类型守卫,封装成显式TypeGuard函数才能触发精确的类型推断。 - predicate为None的分支处理:单独处理该场景,确保过滤所有
None值的同时,让类型系统明确返回结果不含None。
内容的提问来源于stack exchange,提问作者Ziur Olpa
相关产品推荐
相关产品推荐

