Типизация (numpy.typing)
Введено в версии 1.20.
Большая часть API NumPy содержит аннотации типов в стиле PEP 484. Кроме того, пользователям доступны ряд псевдонимов типов, прежде всего два нижеприведенных:
-
ArrayLike: объекты, которые можно преобразовать в массивы -
DTypeLike: объекты, которые можно преобразовать в типы данных
Плагин Mypy
Введено в версии 1.21.
Плагин mypy для управления рядом платформозависимых аннотаций. Его функциональность можно разделить на три части:
- Назначение (зависимых от платформы) точностей определенных подклассов
number, включая такие, какint_,intpиlonglong. См. документацию по скалярным типам для обзора затронутых классов. Без плагина точность всех соответствующих классов будет определена какAny. - Удаление всех подклассов расширенной точности
number, недоступных для данной платформы. В первую очередь это относится к таким, какfloat128иcomplex256. Без плагина все типы с расширенной точностью, с точки зрения mypy, будут доступны для всех платформ. -
Назначение (зависимой от платформы) точности
c_intp. Без плагина тип по умолчанию будетctypes.c_int64.Введено в версии 1.22.
Примеры
Чтобы включить плагин, необходимо добавить его в свой файл конфигурации mypy .
[mypy] plugins = numpy.typing.mypy_plugin
Отличия от API NumPy во время выполнения
NumPy очень гибкий. Попытка статически описать весь спектр возможностей привела бы к типам, которые не очень полезны. По этой причине типизированный API NumPy часто строже, чем API NumPy во время выполнения. В этом разделе описаны некоторые заметные отличия.
ArrayLike
Тип ArrayLike старается избегать создания массивов объектов. Например,
>>> np.array(x**2 for x in range(10)) array(<generator object <genexpr> at ...>, dtype=object)
является корректным кодом NumPy, который создаст массив объектов размерности 0. Однако проверки типов будут жаловаться на приведенный выше пример при использовании типов NumPy. Если вы действительно намеревались сделать вышеперечисленное, то вы можете либо использовать комментарий # type: ignore,
>>> np.array(x**2 for x in range(10)) # type: ignore
либо явно ввести тип объекта массива как Any:
>>> from typing import Any >>> array_like: Any = (x**2 for x in range(10)) >>> np.array(array_like) array(<generator object <genexpr> at ...>, dtype=object)
ndarray
Возможна мутация типа данных массива во время выполнения. Например, следующий код корректен:
>>> x = np.array([1, 2]) >>> x.dtype = np.bool
Этот тип мутации не допускается типами. Пользователи, которые хотят написать статически типизированный код, должны вместо этого использовать метод numpy.ndarray.view для создания представления массива с другим типом данных.
DTypeLike
Тип DTypeLike пытается избежать создания объектов типов данных с использованием словаря полей, как показано ниже:
>>> x = np.dtype({"field1": (float, 1), "field2": (int, 3)})
Хотя это и является корректным кодом NumPy, проверка типов будет жаловаться на него, так как его использование не рекомендуется. См.: Объекты типа данных
Точность чисел
Точность подклассов numpy.number обрабатывается как неизменяемый параметр дженерика (см. NBitBase), упрощая аннотирование процессов, связанных с преобразованием, основанным на точности.
>>> from typing import TypeVar
>>> import numpy as np
>>> import numpy.typing as npt
>>> T = TypeVar("T", bound=npt.NBitBase)
>>> def func(a: "np.floating[T]", b: "np.floating[T]") -> "np.floating[T]":
... ...
Следовательно, такие как float16, float32 и float64 по-прежнему являются подтипами floating, но, в отличие от выполнения, они не обязательно рассматриваются как подклассы.
Timedelta64
Класс timedelta64 не рассматривается как подкласс signedinteger, первый наследуется только от generic при статической проверке типов.
Массивы 0D
Во время выполнения NumPy агрессивно преобразует все переданные массивы 0D в соответствующие экземпляры generic. До введения типизации формы (см. PEP 646) к сожалению, невозможно сделать необходимое различие между массивами 0D и массивами >0D. Таким образом, хотя это не строго верно, все операции, которые потенциально могут выполнить преобразование массива 0D в скаляр, в настоящее время аннотированы как возвращающие исключительно ndarray.
Если заранее известно, что операция будет выполнять преобразование массива 0D в скаляр, то можно вручную исправить ситуацию, используя либо typing.cast, либо комментарий # type: ignore.
Типы данных массивов записей
Тип данных numpy.recarray, и функций создания массивов записей в целом, можно указать двумя способами:
- Непосредственно через аргумент
dtype. - С помощью до пяти вспомогательных аргументов, работающих через
numpy.rec.format_parser:formats,names,titles,alignedиbyteorder.
Эти два подхода в настоящее время типизируются как взаимно исключающие, т.е., если dtype указан, то нельзя указать formats.
Хотя это взаимное исключение не (строго) обеспечивается во время выполнения, сочетание обоих спецификаторов типа данных может привести к неожиданному или даже ошибочному поведению.
API
- numpy.typing.ArrayLike=typing.Union[...]
-
A
Unionrepresenting objects that can be coerced into anndarray.Among others this includes the likes of:
- Числа.
- (Вложенные) последовательности.
- Объекты, реализующие протокол
__array__.
New in version 1.20.
См. также
- array_like:
-
Любое число или последовательность, которые можно интерпретировать как массив ndarray.
Примеры
>>> import numpy as np >>> import numpy.typing as npt >>> def as_array(a: npt.ArrayLike) -> np.ndarray: ... return np.array(a)
- numpy.typing.DTypeLike=typing.Union[...]
-
A
Unionrepresenting objects that can be coerced into adtype.Among others this includes the likes of:
New in version 1.20.
См. также
- Указание и создание типов данных
-
Подробное описание всех объектов, которые можно преобразовать в типы данных.
Примеры
>>> import numpy as np >>> import numpy.typing as npt >>> def as_dtype(d: npt.DTypeLike) -> np.dtype: ... return np.dtype(d)
- numpy.typing.NDArray=numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
-
A
np.ndarray[Any, np.dtype[+ScalarType]]type alias generic w.r.t. itsdtype.type.Can be used during runtime for typing arrays with a given dtype and unspecified shape.
New in version 1.21.
Примеры
>>> import numpy as np >>> import numpy.typing as npt >>> print(npt.NDArray) numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]] >>> print(npt.NDArray[np.float64]) numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]] >>> NDArrayInt = npt.NDArray[np.int_] >>> a: NDArrayInt = np.arange(10) >>> def func(a: npt.ArrayLike) -> npt.NDArray[Any]: ... return np.array(a)
- classnumpy.typing.NBitBase[source]
-
A type representing
numpy.numberprecision during static type checking.Used exclusively for the purpose static type checking,
NBitBaserepresents the base of a hierarchical set of subclasses. Each subsequent subclass is herein used for representing a lower level of precision, e.g.64Bit > 32Bit > 16Bit.New in version 1.20.
Примеры
Below is a typical usage example:
NBitBaseis herein used for annotating a function that takes a float and integer of arbitrary precision as arguments and returns a new float of whichever precision is largest (e.g.np.float16 + np.int64 -> np.float64).>>> from __future__ import annotations >>> from typing import TypeVar, TYPE_CHECKING >>> import numpy as np >>> import numpy.typing as npt >>> T1 = TypeVar("T1", bound=npt.NBitBase) >>> T2 = TypeVar("T2", bound=npt.NBitBase) >>> def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[T1 | T2]: ... return a + b >>> a = np.float16() >>> b = np.int64() >>> out = add(a, b) >>> if TYPE_CHECKING: ... reveal_locals() ... # note: Revealed local types are: ... # note: a: numpy.floating[numpy.typing._16Bit*] ... # note: b: numpy.signedinteger[numpy.typing._64Bit*] ... # note: out: numpy.floating[numpy.typing._64Bit*]
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/reference/typing.html