微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

让 Mypy 对固定/最大长度序列感到满意

如何解决让 Mypy 对固定/最大长度序列感到满意

在使用其他几种语言实现互操作层时,我遇到了如何表示固定长度和最大长度序列的问题。而对于 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一起工作没有问题。我让 sequencearray 生成 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 对这些 sequencearray 类型感到满意?

解决方法

mypy 中没有“最大长度”检查,这意味着集合在运行时已填充,因此在此之前无法检查。

唯一可以用固定长度定义的结构是 Tuple 并且你必须定义每个元素,例如一个 4 个整数的元组看起来像这样:

from typing import Tuple
data: Tuple[int,int,int]
,

您可以使用 Literal[5],请参阅 typing.Literal

一种类型,可用于向类型检查器指示相应的变量或函数参数具有与提供的文字(或多个文字之一)等效的值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。