添加类型

警告

本节仍在进行中。

为函数和参数添加类型提示

Manim 目前正在向库中添加类型提示。在本节中,您将找到有关使用的标准和一些通用指南的信息。

如果你从未使用过类型提示,这是一个很好的入门地方: https://realpython.com/python-type-checking/#hello-types

输入标准

Manim 使用 mypy 来对其代码库进行类型检查。你可以在 mypy.ini 配置文件中找到一系列配置值。 为了能够使用最低支持的 Python 版本中不可用的最新类型特性,请使用 typing_extensions

为了能够使用新的联合语法(|)和内建的下标功能,请使用 from __future__ import annotations 导入。

输入指南

  • Manim 有一个专门的 typing 模块,其中提供了类型别名。 其中大多数可能看起来是多余的,特别是与 numpy 相关的那些。 这是为了预期支持形状类型提示 (相关的问题)。除了 待定的形状支持外,使用正确的类型别名将帮助用户理解 应该使用哪种形状。

  • 对于泛型集合的类型,请查看链接。

  • 对于不返回值的函数(这也适用于__init__),始终使用None的类型提示,例如:

def height(self, value) -> None:
    self.scale_to_fit_height(value)
  • 对于表示路径的变量,请使用在typing模块中定义的StrPathStrOrBytesPath类型别名。

  • *args**kwargs 不应该没有类型(在大多数情况下你可以使用 Any)。

  • 根据PEP 484,使用float而不是int | float

  • 使用 x | y 而不是 Union[x, y]

  • Mobjects 的类型提示是 Mobject,例如:

def match_color(self, mobject: "Mobject"):
    """Match the color with the color of another :class:`~.Mobject`."""
    return self.set_color(mobject.get_color())
  • 始终参数化泛型(list[int] 而不是 listtype[Any] 而不是 type,等等)。这也适用于可调用对象。

rate_func: Callable[[float], float] = lambda t: smooth(1 - t)
  • 当你想“链接”类型提示为相同类型时,使用TypeVar。 考虑Mobject.copy,它返回相同类的新实例。 它将被类型提示为:

T = TypeVar("T")


def copy(self: T) -> T: ...
  • 当函数适用于任何可迭代对象,而不是特定类型时,使用typing.Iterable

  • 优先使用 numpy.typing.NDArray 而不是 numpy.ndarray

import numpy as np

if TYPE_CHECKING:
    import numpy.typing as npt


def foo() -> npt.NDArray[float]:
    return np.array([1, 0, 1])
  • 如果一个方法返回self,请使用typing_extensions.Self

if TYPE_CHECKING:
    from typing_extensions import Self


class CustomMobject:
    def set_color(self, color: ManimColor) -> Self:
        ...
        return self
  • 如果函数每次返回一个特定长度的容器,考虑使用tuple而不是list

def foo() -> tuple[float, float, float]:
    return (0, 0, 0)
  • 如果一个函数可以与一个参数一起工作,只要该参数具有__getitem____iter_____len__方法, 那么该参数的类型提示应该是collections.abc.Mapping。如果它还支持__setitem__和/或__delitem__,它 应该被标记为collections.abc.MutableMapping

  • 将某物类型提示为object意味着只能访问每个Python对象上可用的属性,比如__str__等等。另一方面,对于带有Any类型提示的变量,可以访问任何属性——它比object类型提示更自由,并且使mypy停止对该变量的类型检查。请注意,尽可能保持类型提示尽可能具体。

  • 如果对象仅用于类型提示目的,请将其放在if typing.TYPE_CHECKING保护下,以防止它们在运行时被导入(有助于库的性能)。不要忘记使用from __future__ import annotations导入,以避免运行时出现NameError异常。

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from manim.typing import Vector3D
# type stuff with Vector3D

缺少类型提示的部分是: