为什么mypy不接受list[str]作为list[Optional[str]]且两示例校验结果不一致?
核心原因和规则说明
这个差异是mypy的泛型容器型变规则和上下文类型推断逻辑共同作用的结果,先明确两个基础规则:
- Python typing体系中
List是**不变(invariant)**的泛型类型:如果A是B的子类型,List[A]不会被认为是List[B]的子类型,二者不能直接互相赋值、返回。 - mypy会对新建容器的表达式做上下文类型推断:当表达式所在位置有明确的期望类型时,只要元素类型兼容,mypy会将新建容器的类型直接推导为期望的类型。
示例1报错原因
示例1中some_list由列表推导式生成时,没有指定类型标注,mypy会根据推导式的元素内容,直接将some_list的类型推断为List[str]。
由于List是不变类型,List[str]和函数声明的返回类型List[Optional[str]]不兼容,因此触发类型错误。
如果要让示例1通过校验,可以显式标注some_list的类型:
from typing import List, Optional def myfunc() -> List[Optional[str]]: some_list: List[Optional[str]] = [x for x in "abc"] return some_list
示例2不报错原因
示例2中返回的list(some_list)属于新建列表的表达式,此时mypy会优先读取返回位置的期望类型List[Optional[str]],检查到源列表的元素类型str可以兼容Optional[str](str是Optional[str]的子类型,可以正常赋值),因此会直接将新生成的列表类型推断为List[Optional[str]],符合返回要求,不会报错。
内容的提问来源于stack exchange,提问作者lorg
相关产品推荐
相关产品推荐

