如何在 Python 中键入包含许多元素的元组?

How to type a Tuple with many elements in Python?

我正在试验 typing 模块,我想知道如何正确输入像 Nonagon(9 点多边形)这样的东西,它应该是元组而不是列表,因为它应该是不可变的.

在 2D 中 space,它会是这样的:

Point2D = Tuple[float, float]
Nonagon = Tuple[Point2D, Point2D, Point2D, Point2D, Point2D, Point2D, Point2D, Point2D, Point2D]

nine_points: Nonagon = (
    (0.0, 0.0),
    (6.0, 0.0),
    (6.0, 2.0),
    (2.0, 2.0),
    (6.0, 5.0),
    (2.0, 8.0),
    (6.0, 8.0),
    (6.0, 10.0),
    (0.0, 10.0),
)

是否有任何语法糖可以使 Nonagon 声明更短或更易于阅读?

这无效 Python,但我正在寻找与此类似的内容:

Nonagon = Tuple[*([Point2D] * 9)]  # Not valid Python

或使用NamedTuple

# Not properly detected by static type analysers
Nonagon = NamedTuple('Nonagon', [(f"point_{i}", Point2D) for i in range(9)])  

这不是我想要的:

# Valid but allows for more and less than 9 points
Nonagon = Tuple[Point2D, ...]  

我认为最合适的方法是:

from typing import Annotated

# Valid but needs MinMaxLen and checking logic to be defined from scratch
Nonagon = Annotated[Point2D, MinMaxLen(9, 9)]  

不确定这是否适合您的目的,但 numpy 在这里可能会有用。


import numpy as np
ones = np.ones(9)
nonogon = ones * Point2D

您描述的第一种方式:

Nonagon = Tuple[Point2D, Point2D, Point2D, Point2D, Point2D, Point2D, Point2D, Point2D, Point2D]

是正确的方法,如 2016 python/typing 期中所讨论的那样。是的,它有点难看,但你只需要定义一次。

您可以在此处利用 Annotated,但这最终取决于您的类型检查器是否可以使用您包含的注释。并非所有类型检查器都必须使用这些注释,而拼写出元组中应包含多少个元素是每个(正常运行的)类型检查器都应该识别的内容。

您可以使用types模块。所有类型提示均来自 types.GenericAlias.

来自文档:

Represent a PEP 585 generic type
E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

这意味着您可以通过将类型参数传递给 class 本身来创建自己的类型提示。

>>> Point2D = tuple[float, float]
>>> Nonagon = types.GenericAlias(tuple, (Point2D,)*9)
>>> Nonagon
tuple[tuple[float, float], tuple[float, float], tuple[float, float], tuple[float, float], tuple[float, float], tuple[float, float], tuple[float, float], tuple[float, float], tuple[float, float]]