为何List参数时mypy无法推断类型,换成Iterable则正常?
List与Iterable在mypy类型检查中的差异
场景复现
第一段代码(参数为List[T])
from typing import TypeVar, Union, List T = TypeVar("T", bound=Union[str, int]) def connect_lists(list_1: List[T], list_2: List[T]) -> List[T]: out: List[T] = [] out.extend(list_1) out.extend(list_2) return out connect_lists([1, 2], ["a", "b"])
mypy报错:
error: Cannot infer type argument 1 of "connect_lists" [misc]
第二段代码(参数为Iterable[T])
from typing import TypeVar, Union, Iterable, List T = TypeVar("T", bound=Union[str, int]) def connect_lists(list_1: Iterable[T], list_2: Iterable[T]) -> List[T]: out: List[T] = [] out.extend(list_1) out.extend(list_2) return out connect_lists([1, 2], ["a", "b"])
此时mypy无报错。
差异核心:类型方差的区别
List[T]是不变类型:列表的类型参数是严格不变的——List[int]不能被视为List[Union[str, int]],反过来也不行。当传入List[int]和List[str]时,mypy找不到一个能同时匹配两个参数的T(T的边界是Union[str, int],但List[T]要求两个列表的类型必须完全等于T对应的列表类型),因此无法推导合法的类型参数,直接报错。Iterable[T]是协变类型:Iterable的类型参数是协变的——Iterable[int]是Iterable[Union[str, int]]的子类,Iterable[str]也是。这时候mypy可以把T推导为Union[str, int],两个参数都能适配Iterable[Union[str, int]],所以类型检查顺利通过。
简单总结:列表的不变性导致它无法接受“更宽泛”的类型统一,而Iterable的协变性能让mypy轻松找到兼容的公共类型作为T。
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

