Python 3.9中泛型可调用类型缩小时报错的原因与解决办法
问题解答
错误原因
Python 3.10 开始,内置typing模块支持泛型别名的参数化语法——你可以直接用[]给自定义泛型别名传递参数列表(比如FunctionOrCoroutine[[], str]),这是对相关PEP规范的实现。但在Python 3.9中,typing-extensions里的ParamSpec还不兼容这种简化写法,它要求传递给泛型的参数必须是合法的类型对象,而[]本身不是类型,因此触发TypeError。
解决方法
方案1:显式写出具体类型(最简便)
绕开自定义泛型别名的参数化,直接在注解里写出完整的Union类型:
from typing_extensions import Callable, Awaitable, Union def foo(callback_fn: Union[Callable[[], str], Callable[[], Awaitable[str]]]): pass
方案2:预定义对应参数签名的ParamSpec
先构造一个匹配无参数签名的ParamSpec实例,再传递给你的泛型别名:
from typing_extensions import ParamSpec, TypeVar, Callable, Awaitable, Union _P = ParamSpec("_P") _R = TypeVar("_R") FunctionOrCoroutine = Union[Callable[_P, _R], Callable[_P, Awaitable[_R]]] # 定义无参数的ParamSpec实例 _NoArgs = ParamSpec("_NoArgs") _NoArgs.args = () _NoArgs.kwargs = {} def foo(callback_fn: FunctionOrCoroutine[_NoArgs, str]): pass
方案3:升级到Python 3.10+(彻底解决)
如果项目环境允许,直接升级到Python 3.10或更高版本,就能直接使用你原本的写法,无需修改代码。
内容的提问来源于stack exchange,提问作者Carter Tinney
相关产品推荐
相关产品推荐

