Python 3.12+泛型类型收窄时,类型变量的顺序由何决定?
Python 3.12+ 类型变量实例化顺序问题解析
类型变量的匹配顺序规则
当你用ListLike[str, np.object_]实例化类型别名时,Python类型检查器会按照类型变量首次出现的先后顺序来匹配传入的类型参数:
- 扫描
ListLike的完整定义,提取所有被用到的类型变量,按它们第一次出现的顺序排序。 - 在你的代码里,
T是第一个出现的类型变量(T | list[T]...的第一个元素),U仅在np.ndarray[Any, U]中出现且顺序靠后,所以类型参数的对应关系是第一个参数绑定T,第二个绑定U。 - 这就是为什么
ListLike[str, np.object_]能得到预期结果,反过来传ListLike[np.object_, str]会导致T被绑定为np.object_、U被绑定为str,完全不符合预期。
为什么无法使用关键字传参
当前Python(包括3.12+)的类型系统不支持对类型别名、联合类型的类型变量使用关键字参数传参。关键字传参仅适用于泛型类、泛型函数的实例化场景,比如继承Generic[T, U]的类,而你定义的ListLike属于类型别名,不在支持范围内。
优化写法(降低出错概率)
如果想让类型变量的对应关系更直观,避免因顺序搞错导致的问题,可以将ListLike声明为泛型类型别名(Python 3.12+支持):
from typing import Any, TypeVar, TypeAlias import numpy as np T = TypeVar("T") U = TypeVar("U") ListLike: TypeAlias = T | list[T] | tuple[T, ...] | np.ndarray[Any, U]
虽然依然无法使用关键字传参,但明确的泛型别名定义能让阅读代码的人一眼看出类型参数的顺序对应T和U,减少误用概率。
内容的提问来源于stack exchange,提问作者bzm3r
相关产品推荐
相关产品推荐

