python-mypy错误,不可变列表为元组



我在定义不可变列表类型时遇到一个奇怪的错误:

import sys
from re import split
from typing import Tuple, List, NewType
tokens = split("(d+.d+)", sys.argv[1])
# this works perfectly
# Tokens = NewType("Tokens", List[str])
# print(Tokens(tokens))
# this doesn't work ...
Tokens = NewType("Tokens", Tuple[str])
print(Tokens(tuple(tokens)))

这是我得到的错误:

> mypy main.py
main.py:13: error: Argument 1 to "Tokens" has incompatible type "Tuple[Union[str, Any], ...]"; expected "Tuple[str]"
Found 1 error in 1 file (checked 1 source file)

错误发生的原因

当使用tuple()将列表转换为元组时,Python或至少Mypy不知道元组中元素的确切类型。因此,出现了错误。使用不同的方法将列表转换为元组会导致不同的Mypy错误:

token_x = tuple(tokens)
token_y = tuple(i for i in tokens)
token_z = (*tokens, )
main.py:15: error: Argument 1 to "Tokens" has incompatible type "Tuple[Union[str, Any], ...]"; expected "Tuple[str]"
main.py:16: error: Argument 1 to "Tokens" has incompatible type "Tuple[Union[str, Any], ...]"; expected "Tuple[str]"
main.py:17: error: Argument 1 to "Tokens" has incompatible type "Tuple[Any, ...]"; expected "Tuple[str]"

解决方案

import sys
from re import split
from typing import Tuple, List, NewType
tokens: List[str] = split("(d+.d+)", sys.argv[1]) # explicit annotation on here is great but not necessary
token_x = tuple(tokens)
token_y = tuple(i for i in tokens)
token_z = (*tokens,)
# this works perfectly
# Tokens = NewType("Tokens", List[str])
# print(Tokens(tokens))
# this doesn't work ...
Tokens = NewType("Tokens", Tuple[str, ...]) # explicitly annotate with Tuple[str, ...]
Tokens = NewType("Tokens", Sequence[str]) # or using Sequence[str], which is recommended by Mypy offical document
print(Tokens(token_x))
print(Tokens(token_y))
print(Tokens(token_z))

附录

相关问题:如何注释采用可变长度元组的函数?(可变元组类型注释(

Tuple[str, ...]的含义:元组中所有元素的str, ...表示为str

Mypy官方文件:https://mypy.readthedocs.io/en/stable/kinds_of_types.html#tuple-类型

最新更新