__init__.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. """
  2. ============================
  3. Typing (:mod:`numpy.typing`)
  4. ============================
  5. .. versionadded:: 1.20
  6. Large parts of the NumPy API have :pep:`484`-style type annotations. In
  7. addition a number of type aliases are available to users, most prominently
  8. the two below:
  9. - `ArrayLike`: objects that can be converted to arrays
  10. - `DTypeLike`: objects that can be converted to dtypes
  11. .. _typing-extensions: https://pypi.org/project/typing-extensions/
  12. Mypy plugin
  13. -----------
  14. .. versionadded:: 1.21
  15. .. automodule:: numpy.typing.mypy_plugin
  16. .. currentmodule:: numpy.typing
  17. Differences from the runtime NumPy API
  18. --------------------------------------
  19. NumPy is very flexible. Trying to describe the full range of
  20. possibilities statically would result in types that are not very
  21. helpful. For that reason, the typed NumPy API is often stricter than
  22. the runtime NumPy API. This section describes some notable
  23. differences.
  24. ArrayLike
  25. ~~~~~~~~~
  26. The `ArrayLike` type tries to avoid creating object arrays. For
  27. example,
  28. .. code-block:: python
  29. >>> np.array(x**2 for x in range(10))
  30. array(<generator object <genexpr> at ...>, dtype=object)
  31. is valid NumPy code which will create a 0-dimensional object
  32. array. Type checkers will complain about the above example when using
  33. the NumPy types however. If you really intended to do the above, then
  34. you can either use a ``# type: ignore`` comment:
  35. .. code-block:: python
  36. >>> np.array(x**2 for x in range(10)) # type: ignore
  37. or explicitly type the array like object as `~typing.Any`:
  38. .. code-block:: python
  39. >>> from typing import Any
  40. >>> array_like: Any = (x**2 for x in range(10))
  41. >>> np.array(array_like)
  42. array(<generator object <genexpr> at ...>, dtype=object)
  43. ndarray
  44. ~~~~~~~
  45. It's possible to mutate the dtype of an array at runtime. For example,
  46. the following code is valid:
  47. .. code-block:: python
  48. >>> x = np.array([1, 2])
  49. >>> x.dtype = np.bool
  50. This sort of mutation is not allowed by the types. Users who want to
  51. write statically typed code should instead use the `numpy.ndarray.view`
  52. method to create a view of the array with a different dtype.
  53. DTypeLike
  54. ~~~~~~~~~
  55. The `DTypeLike` type tries to avoid creation of dtype objects using
  56. dictionary of fields like below:
  57. .. code-block:: python
  58. >>> x = np.dtype({"field1": (float, 1), "field2": (int, 3)})
  59. Although this is valid NumPy code, the type checker will complain about it,
  60. since its usage is discouraged.
  61. Please see : :ref:`Data type objects <arrays.dtypes>`
  62. Number precision
  63. ~~~~~~~~~~~~~~~~
  64. The precision of `numpy.number` subclasses is treated as a invariant generic
  65. parameter (see :class:`~NBitBase`), simplifying the annotating of processes
  66. involving precision-based casting.
  67. .. code-block:: python
  68. >>> from typing import TypeVar
  69. >>> import numpy as np
  70. >>> import numpy.typing as npt
  71. >>> T = TypeVar("T", bound=npt.NBitBase)
  72. >>> def func(a: np.floating[T], b: np.floating[T]) -> np.floating[T]:
  73. ... ...
  74. Consequently, the likes of `~numpy.float16`, `~numpy.float32` and
  75. `~numpy.float64` are still sub-types of `~numpy.floating`, but, contrary to
  76. runtime, they're not necessarily considered as sub-classes.
  77. .. deprecated:: 2.3
  78. The :class:`~numpy.typing.NBitBase` helper is deprecated and will be
  79. removed in a future release. Prefer expressing precision relationships via
  80. ``typing.overload`` or ``TypeVar`` definitions bounded by concrete scalar
  81. classes. For example:
  82. .. code-block:: python
  83. from typing import TypeVar
  84. import numpy as np
  85. S = TypeVar("S", bound=np.floating)
  86. def func(a: S, b: S) -> S:
  87. ...
  88. or in the case of different input types mapping to different output types:
  89. .. code-block:: python
  90. from typing import overload
  91. import numpy as np
  92. @overload
  93. def phase(x: np.complex64) -> np.float32: ...
  94. @overload
  95. def phase(x: np.complex128) -> np.float64: ...
  96. @overload
  97. def phase(x: np.clongdouble) -> np.longdouble: ...
  98. def phase(x: np.complexfloating) -> np.floating:
  99. ...
  100. Timedelta64
  101. ~~~~~~~~~~~
  102. The `~numpy.timedelta64` class is not considered a subclass of
  103. `~numpy.signedinteger`, the former only inheriting from `~numpy.generic`
  104. while static type checking.
  105. 0D arrays
  106. ~~~~~~~~~
  107. During runtime numpy aggressively casts any passed 0D arrays into their
  108. corresponding `~numpy.generic` instance. Until the introduction of shape
  109. typing (see :pep:`646`) it is unfortunately not possible to make the
  110. necessary distinction between 0D and >0D arrays. While thus not strictly
  111. correct, all operations that can potentially perform a 0D-array -> scalar
  112. cast are currently annotated as exclusively returning an `~numpy.ndarray`.
  113. If it is known in advance that an operation *will* perform a
  114. 0D-array -> scalar cast, then one can consider manually remedying the
  115. situation with either `typing.cast` or a ``# type: ignore`` comment.
  116. Record array dtypes
  117. ~~~~~~~~~~~~~~~~~~~
  118. The dtype of `numpy.recarray`, and the :ref:`routines.array-creation.rec`
  119. functions in general, can be specified in one of two ways:
  120. * Directly via the ``dtype`` argument.
  121. * With up to five helper arguments that operate via `numpy.rec.format_parser`:
  122. ``formats``, ``names``, ``titles``, ``aligned`` and ``byteorder``.
  123. These two approaches are currently typed as being mutually exclusive,
  124. *i.e.* if ``dtype`` is specified than one may not specify ``formats``.
  125. While this mutual exclusivity is not (strictly) enforced during runtime,
  126. combining both dtype specifiers can lead to unexpected or even downright
  127. buggy behavior.
  128. API
  129. ---
  130. """
  131. # NOTE: The API section will be appended with additional entries
  132. # further down in this file
  133. # pyright: reportDeprecated=false
  134. from numpy._typing import ArrayLike, DTypeLike, NBitBase, NDArray
  135. __all__ = ["ArrayLike", "DTypeLike", "NBitBase", "NDArray"]
  136. __DIR = __all__ + [k for k in globals() if k.startswith("__") and k.endswith("__")]
  137. __DIR_SET = frozenset(__DIR)
  138. def __dir__() -> list[str]:
  139. return __DIR
  140. def __getattr__(name: str) -> object:
  141. if name == "NBitBase":
  142. import warnings
  143. # Deprecated in NumPy 2.3, 2025-05-01
  144. warnings.warn(
  145. "`NBitBase` is deprecated and will be removed from numpy.typing in the "
  146. "future. Use `@typing.overload` or a `TypeVar` with a scalar-type as upper "
  147. "bound, instead. (deprecated in NumPy 2.3)",
  148. DeprecationWarning,
  149. stacklevel=2,
  150. )
  151. return NBitBase
  152. if name in __DIR_SET:
  153. return globals()[name]
  154. raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
  155. if __doc__ is not None:
  156. from numpy._typing._add_docstring import _docstrings
  157. __doc__ += _docstrings
  158. __doc__ += '\n.. autoclass:: numpy.typing.NBitBase\n'
  159. del _docstrings
  160. from numpy._pytesttester import PytestTester
  161. test = PytestTester(__name__)
  162. del PytestTester