输入已知长度的序列或列表的提示

问题描述 投票:0回答:4

我知道指定

List
的长度是无效的,如下所示:

List[float, float, float]  # List of 3 floats

或:

List[float * 10]  # List of 10 floats

这可能吗?

python python-typing
4个回答
69
投票

你不能。列表是可变的、可变长度结构。如果您需要固定长度的结构,请使用元组:

Tuple[float, float, float, float, float, float, float, float, float, float]

或者更好的是,使用命名元组,它既有索引也有命名属性:

class BunchOfFloats(NamedTuple):
    foo: float
    bar: float
    baz: float
    spam: float
    ham: float
    eggs: float
    monty: float
    python: float
    idle: float
    cleese: float

列表对于固定长度的数据结构来说是错误的数据类型。


56
投票

typing.Annotated
在这里可以很方便。它允许您指定任意元数据来键入提示:

Annotated[list[float], 3]

刚接触

Annotated
? 这是文档的片段:

如果库(或工具)遇到类型提示

Annotated[T, x]
并且对于元数据没有特殊逻辑
x
,它应该忽略它并简单地将类型视为
T

值得注意的是,

mypy
对于此类事情有一个“未完成的请求”(截至 2022 年 11 月开放)。 同时,将 Annotated 视为开发人员的可读性,而不是自动检查(除非您开发检查工具)。
    


15
投票

这是来自

typing 模块的定义和文档字符串: class Tuple(tuple, extra=tuple, metaclass=TupleMeta): """Tuple type; Tuple[X, Y] is the cross-product type of X and Y. Example: Tuple[T1, T2] is a tuple of two elements corresponding to type variables T1 and T2. Tuple[int, float, str] is a tuple of an int, a float and a string. To specify a variable-length tuple of homogeneous type, use Tuple[T, ...]. """ __slots__ = () def __new__(cls, *args, **kwds): if _geqv(cls, Tuple): raise TypeError("Type Tuple cannot be instantiated; " "use tuple() instead") return _generic_new(tuple, cls, *args, **kwds)

由于列表是可变的、可变长度的类型,因此使用类型声明来指定固定大小没有任何意义。


8
投票
Martijn Pieters 的回答

。因为我想要一个“快速”和“简单”的方法来解决这个问题。 所以我首先尝试了这里列出的其他建议。

注意:我使用 VSCode 和 Pylance 作为语言服务器

Zaffy 的回答

是我最喜欢的 def demystify(mystery: Annotated[Tuple[int], 6]): a, b, c, d, e, f = mystery print(a, b, c, d, e, f)

该函数的提示如下所示:
demystify: (mystery: Tuple[int]) -> None

另外,我还收到了 Pylance 错误

Tuple size mismatch: expected 6 but received
a, b, c, d, e, f = mystery
接下来我尝试了

Tuple[6 * (int, )]

,这是balu在

Martijn Pieters回答的评论中提到的
def demystify(mystery: Tuple[6 * (int,)]): a, b, c, e, f, g = mystery print(a, b, c, e, f, g)

导致与之前相同的 Pylance 错误。
该功能的提示是这样的:
demystify: (mystery: Tuple[Tuple[Type[int], ...]]) -> None

回到写下预期长度:

def demystify(mystery: Tuple[int, int, int, int, int, int]): a, b, c, e, f, g = mystery print(a, b, c, e, f, g)

这解决了 Pylance 错误,并给了我一个“清晰”的功能提示:
demystify: (mystery: Tuple[int, int, int, int, int, int]) -> None

但就像约翰·布罗迪一样,我对这个解决方案并不满意。

现在回到最初不需要的答案:

class MysteryType(NamedTuple): a: int b: int c: int d: int e: int f: int g: int def demystify(mystery: MysteryType): print(*mystery)

函数提示现在看起来更加神秘:
demystify: (mystery: MysteryType) -> None

,但是创建一个新的 MysteryType 为我提供了我需要的所有信息:

(a: int, b: int, c: int, d: int, e: int, f: int, g: int)
我还可以在其他方法和函数中使用 MysteryType,而无需计算类型提示。

所以,长话短说,解释一下 Python 的禅宗:

NamedTuples 是一个非常棒的想法——让我们做更多这样的事情!

© www.soinside.com 2019 - 2024. All rights reserved.