如何正确为构建Sequence列表的Python表达式添加类型注解解决mypy报错
报错核心原因
- 无显式类型注解时,mypy会根据列表首个元素的类型推断整个列表的元素类型:编写
[('foo',)]时,mypy直接将其判定为list[tuple[str]],后续拼接list[tuple[str, str]]自然触发类型不匹配错误。 List属于不变型(invariant)类型:就算给变量添加list[Sequence[str]]的注解,等号右侧的拼接表达式会先被独立推断为list[tuple[str]],不变型规则不允许将list[tuple[str]]直接赋值给list[Sequence[str]]——即便tuple[str]本身是Sequence[str]的子类型。
最优简洁方案
用列表解包语法配合显式类型注解即可,无需逐次调用append,也无需给每个元素加cast:
from typing import Sequence # 假设a、b为函数返回值/列表推导生成的列表,元素可以是任意长度的字符串元组,也可以是字符串列表 a = [('foo',)] b = [('bar', 'baz')] x: list[Sequence[str]] = [*a, *b]
这种写法下,mypy会直接以你声明的list[Sequence[str]]作为目标类型,逐一检查解包传入的每个元素是否符合Sequence[str]要求,只要元素是字符串组成的序列就能通过检查,完全兼容不同长度的元组、列表类型。
如果使用Python 3.9+版本,可以直接从collections.abc导入Sequence,无需依赖typing模块的兼容写法;如果需要多处使用该类型,可以提前定义类型别名简化代码:
from collections.abc import Sequence from typing import TypeAlias StrSeq: TypeAlias = Sequence[str] def get_part1() -> list[tuple[str]]: return [('foo',)] def get_part2() -> list[tuple[str, str]]: return [('bar', 'baz')] # 支持任意数量的列表拼接,直接解包即可 x: list[StrSeq] = [*get_part1(), *get_part2()]
可选替代写法
如果想保留+的拼接习惯,只需先声明带类型的空列表,再用+=拼接即可,不需要对每个元素做类型转换:
from typing import Sequence x: list[Sequence[str]] = [] x += [('foo',)] x += [('bar', 'baz')]
这种写法比逐次append更简洁,但可读性略逊于直接解包的方案。
内容的提问来源于stack exchange,提问作者jamesdlin
相关产品推荐
相关产品推荐

