在与其他几种语言实现互操作层时,我遇到了如何表示固定和最大长度序列的问题。而对于 Python 来说,其他语言需要提供完整的类型信息并不重要。面向用户的 API 应如下所示:
@dataclass
class MyStruct:
name: bounded_str[12] # here 12 is a max length
data: sequence[int8, 20] # here 20 is the max length
other_data: array[float32, 10] # here 10 is a fixed length
现在我可以毫无问题地让它与普通的 python 一起工作。我让
sequence
和 array
生成 Annotated
类型,如下所示:
class ArrayMeta(type):
def __getitem__(cls, tup):
if type(tup) != tuple or len(tup) != 2 or type(tup[1]) != int:
return TypeError("An array takes two arguments: a subtype and a constant length.")
return Annotated[Sequence[tup[0]], array(*tup)]
class array(metaclass=ArrayMeta):
def __init__(self, subtype, length):
self.subtype = subtype
self.length = length
这使得数据类具有完全可接受的
Annotated[Sequence[subtype], ...]
,我可以使用get_type_hints
检查注释并确定互操作所需的“真实”类型,生成验证器/序列化器等。
现在,当我们将 Mypy 引入其中时,问题就出现了。 Mypy 不认为
array
类型有效,这很公平。然而,到目前为止,我制作有效版本的任何尝试都被难住了,因为 Generic
不会采用值类型:
T = TypeVar('T')
V = TypeVar('V')
class MyArray(Protocol, Generic[T, V]):
def __getitem__(self, key: int) -> T: ...
def __len__(self):
return V
a: MyArray[int, 5] = [0, 1, 2, 3, 4]
>>> TypeError: Parameters to generic types must be types. Got 5.
有没有办法让 Mypy 对这些
sequence
和 array
类型感到满意?
mypy 中没有“最大长度”检查,这意味着集合在运行时已填充,因此在此之前无法进行检查。
唯一可以定义固定长度的结构是
Tuple
,并且您必须定义每个元素,例如其中包含 4 个整数的元组如下所示:
from typing import Tuple
data: Tuple[int, int, int, int]