Python类型注解如何约束多个参数的列表元素为相同类型
解决方案
要实现多个关联位置的类型统一校验,直接使用typing.TypeVar定义泛型类型占位符即可,它会强制所有标注了该占位符的参数、返回值绑定为同一个具体类型。
无类型范围限制的写法
如果不需要限定sameType的可选范围,允许匹配任意类型,写法如下:
import typing as _T # 定义泛型类型变量,名称可自定义,作为统一类型的占位符 T = _T.TypeVar("T") def foo(x: _T.List[T], y: _T.List[T]) -> _T.List[T]: ...
这个写法下mypy会自动推导传入参数的实际类型:
- 调用
foo([1], [1.0])时,会识别到第一个列表元素为int、第二个为float,直接抛出类型不匹配错误 - 调用
foo([1, 2], [3, 4])会正常通过校验,返回值会被自动识别为List[int] - 传入任意其他类型的列表(比如
List[str]、List[dict])都可以正常校验,只要两个入参列表的元素类型一致就不会报错
限定类型范围的写法
如果需要约束sameType只能是某几个类型中的一种(比如提到的Union[int, float]范围),只需要在定义TypeVar时把允许的类型作为约束参数传入即可:
import typing as _T # 约束类型变量只能匹配int或float类型,不接受其他类型 T = _T.TypeVar("T", int, float) def foo(x: _T.List[T], y: _T.List[T]) -> _T.List[T]: ...
这个写法会同时满足两个校验规则:
- 两个入参列表、返回值列表的元素类型必须完全统一
- 统一后的元素类型只能是
int或者float,传入其他类型(比如str)的列表会直接报错
比如调用foo(["a"], ["b"])会触发类型错误,调用foo([1], [1.0])依然会因为两个列表元素类型不统一报错,调用foo([1.0], [2.5])会正常通过,返回值被识别为List[float]。
注意:不要直接在
List里内嵌Union做注解,这种写法只会标记单个列表的元素可以是Union范围内的任意类型,不会做跨参数的类型一致性绑定,自然无法校验两个列表的元素类型是否统一。
如果是Python 3.9及以上版本,可以直接用内置类型list[T]替代_T.List[T],写法更简洁。
内容的提问来源于stack exchange,提问作者norok2
相关产品推荐
相关产品推荐

