Типизация (numpy.typing)#
Новое в версии 1.20.
Большие части API NumPy имеют PEP 484-стилевые аннотации типов. Кроме того, пользователям доступен ряд псевдонимов типов, наиболее заметные из которых приведены ниже:
ArrayLike: объекты, которые можно преобразовать в массивыDTypeLike: объекты, которые можно преобразовать в dtypes
Mypy plugin#
Новое в версии 1.21.
A mypy плагин для управления несколькими платформенно-специфичными аннотациями. Его функциональность можно разделить на три отдельные части:
Назначение (зависящих от платформы) точностей определённых
numberподклассы, включая такие какint_,intpиlonglong. См. документацию по скалярные типы для полного обзора затронутых классов. Без плагина точность всех соответствующих классов будет выведена какAny.Удаление всей расширенной точности
numberподклассы, которые недоступны для рассматриваемой платформы. Наиболее заметно это включает такие классы, какfloat128иcomplex256. Без плагина все расширенные типы точности будут, насколько это касается mypy, доступны на всех платформах.Назначение (зависимой от платформы) точности
c_intp. Без плагина тип по умолчанию будетctypes.c_int64.Добавлено в версии 1.22.
Устарело с версии 2.3: The numpy.typing.mypy_plugin точка входа устарела в пользу
независимой от платформы статической проверки типов. Удалить
numpy.typing.mypy_plugin из plugins раздел вашей конфигурации mypy;
если это выявит новые ошибки, пожалуйста, откройте issue с
минимальным воспроизводимым примером.
Примеры#
Чтобы включить плагин, необходимо добавить его в свой mypy файл конфигурации:
[mypy]
plugins = numpy.typing.mypy_plugin
Отличия от API NumPy во время выполнения#
NumPy очень гибок. Попытка статически описать весь диапазон возможностей привела бы к типам, которые не очень полезны. По этой причине типизированный API NumPy часто строже, чем API NumPy во время выполнения. В этом разделе описаны некоторые заметные различия.
ArrayLike#
The ArrayLike тип пытается избежать создания массивов объектов. Например,
>>> np.array(x**2 for x in range(10))
array( 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( at ...>, dtype=object)
ndarray#
Возможно изменять dtype массива во время выполнения. Например, следующий код является допустимым:
>>> x = np.array([1, 2])
>>> x.dtype = np.bool
Такой вид мутации не разрешён типами. Пользователи, которые хотят
писать статически типизированный код, должны вместо этого использовать numpy.ndarray.view
метод для создания представления массива с другим dtype.
DTypeLike#
The DTypeLike тип пытается избежать создания объектов dtype с использованием словаря полей, как показано ниже:
>>> x = np.dtype({"field1": (float, 1), "field2": (int, 3)})
Хотя это допустимый код NumPy, проверка типов будет жаловаться на него, так как его использование не рекомендуется. Пожалуйста, смотрите : Объекты типов данных
Вклад в 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, но, в отличие от
времени выполнения, они не обязательно считаются подклассами.
Устарело с версии 2.3: The NBitBase вспомогательная функция устарела и будет удалена в будущем выпуске. Предпочитайте выражать отношения точности через
typing.overload или TypeVar определения, ограниченные конкретными скалярными
классами. Например:
from typing import TypeVar import numpy as np S = TypeVar("S", bound=np.floating) def func(a: S, b: S) -> S: ...или в случае разных типов входных данных, отображающихся на разные типы выходных данных:
from typing import overload
import numpy as np
@overload
def phase(x: np.complex64) -> np.float32: ...
@overload
def phase(x: np.complex128) -> np.float64: ...
@overload
def phase(x: np.clongdouble) -> np.longdouble: ...
def phase(x: np.complexfloating) -> np.floating:
...
Timedelta64#
The timedelta64 класс не считается подклассом
signedinteger, причём первый наследует только от generic
при статической проверке типов.
0D массивы#
Во время выполнения numpy агрессивно преобразует любые переданные 0D массивы в их соответствующие generic экземпляр. До введения типизации формы
(см. PEP 646) к сожалению невозможно сделать
необходимое различие между 0D и >0D массивами. Хотя это не строго
корректно, все операции, которые потенциально могут выполнить приведение 0D-массива -> скаляра,
в настоящее время аннотированы как возвращающие исключительно ndarray.
Если заранее известно, что операция будет выполнить
преобразование 0D-массива -> скаляр, тогда можно вручную исправить
ситуацию с помощью typing.cast или # type: ignore комментарий.
Типы данных записей массивов#
Тип данных numpy.recarrayдолжны быть включены в старые категории. Значения, которые были в
удаленных категориях, будут установлены в NaN Создание массивов записей
функции в целом могут быть указаны одним из двух способов:
Напрямую через
dtypeаргумент.С помощью до пяти вспомогательных аргументов, которые работают через
numpy.rec.format_parser:formats,names,titles,alignedиbyteorder.
Эти два подхода в настоящее время типизированы как взаимоисключающие,
т.е. if dtype указано, то нельзя указывать formats.
Хотя эта взаимоисключительность не (строго) применяется во время выполнения, комбинирование обоих спецификаторов типов данных может привести к неожиданному или даже ошибочному поведению.
API#
- numpy.typing.ArrayLike = typing.Union[...]#
A
Unionпредставляющий объекты, которые могут быть приведены кndarray.Среди прочего это включает такие вещи, как:
Скаляры.
(Вложенные) последовательности.
Объекты, реализующие __array__ протокол.
Новое в версии 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
Unionпредставляющие объекты, которые могут быть приведены кdtype.Среди прочего это включает такие вещи, как:
Новое в версии 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[tuple[typing.Any, ...], numpy.dtype[~_ScalarT]]#
A
np.ndarray[tuple[Any, ...], np.dtype[ScalarT]]псевдоним типа общий относительно егоdtype.type.Может использоваться во время выполнения для типизации массивов с заданным dtype и неопределенной формой.
Новое в версии 1.21.
Примеры
>>> import numpy as np >>> import numpy.typing as npt >>> print(npt.NDArray) numpy.ndarray[tuple[typing.Any, ...], numpy.dtype[~_ScalarT]] >>> print(npt.NDArray[np.float64]) numpy.ndarray[tuple[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)
- класс numpy.typing.NBitBase[источник]#
Тип, представляющий
numpy.numberточность во время статической проверки типов.Используется исключительно для статической проверки типов,
NBitBaseпредставляет основу иерархического набора подклассов. Каждый последующий подкласс используется для представления более низкого уровня точности, например,64Bit > 32Bit > 16Bit.Новое в версии 1.20.
Устарело с версии 2.3: Используйте
@typing.overloadилиTypeVarсо скалярным типом в качестве верхней границы, вместо этого.Примеры
Ниже приведен типичный пример использования:
NBitBaseздесь используется для аннотации функции, которая принимает float и целое число произвольной точности в качестве аргументов и возвращает новый float с наибольшей точностью (например,np.float16 + np.int64 -> np.float64).>>> from typing import TypeVar, TYPE_CHECKING >>> import numpy as np >>> import numpy.typing as npt >>> S = TypeVar("S", bound=npt.NBitBase) >>> T = TypeVar("T", bound=npt.NBitBase) >>> def add(a: np.floating[S], b: np.integer[T]) -> np.floating[S | T]: ... 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*]