NumPy 2.4.0 Release Notes#
Highlights#
We’ll choose highlights for this release near the end of the release cycle.
Deprecations#
Setting the strides attribute is deprecated#
Setting the strides attribute is now deprecated since mutating
an array is unsafe if an array is shared, especially by multiple
threads. As an alternative, you can create a new view (no copy) via:
* np.lib.stride_tricks.strided_window_view if applicable,
* np.lib.stride_tricks.as_strided for the general case,
* or the np.ndarray constructor (buffer is the original array) for a light-weight version.
(gh-28925)
Positional out argument to np.maximum, np.minimum is deprecated#
Passing the output array out positionally to numpy.maximum and
numpy.minimum is deprecated. For example, np.maximum(a, b, c) will
emit a deprecation warning, since c is treated as the output buffer
rather than a third input.
Always pass the output with the keyword form, e.g.
np.maximum(a, b, out=c). This makes intent clear and simplifies
type annotations.
(gh-29052)
align= must be passed as boolean to np.dtype()#
When creating a new dtype a VisibleDeprecationWarning will be
given if align= is not a boolean.
This is mainly to prevent accidentally passing a subarray align flag where it
has no effect, such as np.dtype("f8", 3) instead of np.dtype(("f8", 3)).
We strongly suggest to always pass align= as a keyword argument.
(gh-29301)
Assertion and warning control utilities are deprecated#
np.testing.assert_warns and np.testing.suppress_warnings are deprecated.
Use warnings.catch_warnings, warnings.filterwarnings, pytest.warns, or
pytest.filterwarnings instead.
(gh-29550)
Expired deprecations#
Raise TypeError on attempt to convert array with ndim > 0 to scalar#
Conversion of an array with ndim > 0 to a scalar was deprecated in NumPy 1.25. Now, attempting to do so raises TypeError. Ensure you extract a single element from your array before performing this operation.
(gh-29841)
Remove numpy.linalg.linalg and numpy.fft.helper#
The following were deprecated in NumPy 2.0 and have been moved to private modules
numpy.linalg.linalgUsenumpy.linalginstead.numpy.fft.helperUsenumpy.fftinstead.
(gh-29909)
Remove interpolation parameter from quantile and percentile functions#
The interpolation parameter was deprecated in NumPy 1.22.0 and has been
removed from the following functions:
numpy.percentilenumpy.nanpercentilenumpy.quantilenumpy.nanquantile
Use the method parameter instead.
(gh-29973)
Removed numpy.in1d#
numpy.in1d has been deprecated since NumPy 2.0 and is now removed in favor of numpy.isin.
(gh-29978)
Removed numpy.ndindex.ndincr()#
The ndindex.ndincr() method has been deprecated since NumPy 1.20 and is now removed;
use next(ndindex) instead.
(gh-29980)
Removed fix_imports parameter from numpy.save#
The fix_imports parameter was deprecated in NumPy 2.1.0 and is now removed.
This flag has been ignored since NumPy 1.17 and was only needed to support loading files in Python 2 that were written in Python 3.
(gh-29984)
Removal of four undocumented ndarray.ctypes methods#
Four undocumented methods of the ndarray.ctypes object have been removed:
_ctypes.get_data()(use_ctypes.datainstead)_ctypes.get_shape()(use_ctypes.shapeinstead)_ctypes.get_strides()(use_ctypes.stridesinstead)_ctypes.get_as_parameter()(use_ctypes._as_parameter_instead)
These methods have been deprecated since NumPy 1.21.
(gh-29986)
Remove newshape parameter from numpy.reshape#
The newshape parameter was deprecated in NumPy 2.1.0 and has been
removed from numpy.reshape. Pass it positionally or use shape=
on newer NumPy versions.
(gh-29994)
Removal of deprecated functions and arguments#
The following long-deprecated APIs have been removed:
numpy.trapz— deprecated since NumPy 2.0 (2023-08-18). Usenumpy.trapezoidorscipy.integratefunctions instead.dispfunction — deprecated from 2.0 release and no longer functional. Use your own printing function instead.biasandddofarguments innumpy.corrcoef— these had no effect since NumPy 1.10.
(gh-29997)
Remove delimitor parameter from numpy.ma.mrecords.fromtextfile()#
The delimitor parameter was deprecated in NumPy 1.22.0 and has been
removed from numpy.ma.mrecords.fromtextfile(). Use delimiter instead.
(gh-30021)
Compatibility notes#
NumPy’s C extension modules have begun to use multi-phase initialisation, as defined by PEP 489. As part of this, a new explicit check has been added that each such module is only imported once per Python process. This comes with the side-effect that deleting
numpyfromsys.modulesand re-importing it will now fail with anImportError. This has always been unsafe, with unexpected side-effects, though did not previously raise an error.(gh-29030)
numpy.roundnow always returns a copy. Previously, it returned a view for integer inputs fordecimals >= 0and a copy in all other cases. This change bringsroundin line withceil,floorandtrunc.(gh-29137)
The Macro NPY_ALIGNMENT_REQUIRED has been removed#
The macro was defined in the npy_cpu.h file, so might be regarded as semipublic. As it turns out, with modern compilers and hardware it is almost always the case that alignment is required, so numpy no longer uses the macro. It is unlikely anyone uses it, but you might want to compile with the -Wundef flag or equivalent to be sure.
(gh-29094)
C API changes#
The NPY_SORTKIND enum has been enhanced with new variables#
This is of interest if you are using PyArray_Sort or PyArray_ArgSort.
We have changed the semantics of the old names in the NPY_SORTKIND enum and
added new ones. The changes are backward compatible, and no recompilation is
needed. The new names of interest are:
NPY_SORT_DEFAULT – default sort (same value as NPY_QUICKSORT)
NPY_SORT_STABLE – the sort must be stable (same value as NPY_MERGESORT)
NPY_SORT_DESCENDING – the sort must be descending
The semantic change is that NPY_HEAPSORT is mapped to NPY_QUICKSORT when used. Note that NPY_SORT_DESCENDING is not yet implemented.
(gh-29642)
New NPY_DT_get_constant slot for DType constant retrieval#
A new slot NPY_DT_get_constant has been added to the DType API, allowing
dtype implementations to provide constant values such as machine limits and
special values. The slot function has the signature:
int get_constant(PyArray_Descr *descr, int constant_id, void *ptr)
It returns 1 on success, 0 if the constant is not available, or -1 on error. The function is always called with the GIL held and may write to unaligned memory.
Integer constants (marked with the 1 << 16 bit) return npy_intp values,
while floating-point constants return values of the dtype’s native type.
Implementing this can be used by user DTypes to provide numpy.finfo values.
(gh-29836)
A new PyUFunc_AddLoopsFromSpecs convenience function has been added to the C API.#
This function allows adding multiple ufunc loops from their specs in one call using a NULL-terminated array of PyUFunc_LoopSlot structs. It allows registering sorting and argsorting loops using the new ArrayMethod API.
(gh-29900)
New Features#
Let
np.sizeaccept multiple axes.(gh-29240)
Extend numpy.pad to accept a dictionary for the pad_width argument.
(gh-29273)
StringDType fill_value support in numpy.ma.MaskedArray#
Masked arrays now accept and preserve a Python str as their fill_value when
using the variable‑width StringDType (kind 'T'), including through slicing
and views. The default is 'N/A' and may be overridden by any valid string.
This fixes issue gh‑29421 and was
implemented in pull request gh‑29423.
(gh-29423)
ndmax option for numpy.array#
The ndmax option is now available for numpy.array.
It explicitly limits the maximum number of dimensions created from nested sequences.
This is particularly useful when creating arrays of list-like objects with dtype=object.
By default, NumPy recurses through all nesting levels to create the highest possible
dimensional array, but this behavior may not be desired when the intent is to preserve
nested structures as objects. The ndmax parameter provides explicit control over
this recursion depth.
# Default behavior: Creates a 2D array
>>> a = np.array([[1, 2], [3, 4]], dtype=object)
>>> a
array([[1, 2],
[3, 4]], dtype=object)
>>> a.shape
(2, 2)
# With ndmax=1: Creates a 1D array
>>> b = np.array([[1, 2], [3, 4]], dtype=object, ndmax=1)
>>> b
array([list([1, 2]), list([3, 4])], dtype=object)
>>> b.shape
(2,)
(gh-29569)
Warning emitted when using where without out#
Ufuncs called with a where mask and without an out positional or kwarg will
now emit a warning. This usage tends to trip up users who expect some value in
output locations where the mask is False (the ufunc will not touch those
locations). The warning can be supressed by using out=None.
(gh-29813)
DType sorting and argsorting supports the ArrayMethod API#
User-defined dtypes can now implement custom sorting and argsorting using the ArrayMethod API. This mechanism can be used in place of the PyArray_ArrFuncs slots which may be deprecated in the future.
The sorting and argsorting methods are registered by passing the arraymethod specs that implement the operations to the new PyUFunc_AddLoopsFromSpecs function. See the ArrayMethod API documentation for details.
(gh-29900)
Improvements#
Fix flatiter indexing edge cases#
The flatiter object now shares the same index preparation logic as
ndarray, ensuring consistent behavior and fixing several issues where
invalid indices were previously accepted or misinterpreted.
Key fixes and improvements:
Stricter index validation
Boolean non-array indices like
arr.flat[[True, True]]were incorrectly treated asarr.flat[np.array([1, 1], dtype=int)]. They now raise an index error. Note that indices that match the iterator’s shape are expected to not raise in the future and be handled as regular boolean indices. Usenp.asarray(<index>)if you want to match that behavior.Float non-array indices were also cast to integer and incorrectly treated as
arr.flat[np.array([1.0, 1.0], dtype=int)]. This is now deprecated and will be removed in a future version.0-dimensional boolean indices like
arr.flat[True]are also deprecated and will be removed in a future version.
Consistent error types:
Certain invalid
flatiterindices that previously raised ValueError now correctly raise IndexError, aligning withndarraybehavior.Improved error messages:
The error message for unsupported index operations now provides more specific details, including explicitly listing the valid index types, instead of the generic
IndexError: unsupported index operation.
(gh-28590)
Improved error message for assert_array_compare#
The error message generated by assert_array_compare which is used by functions like assert_allclose, assert_array_less etc. now also includes information about the indices at which the assertion fails.
(gh-29112)
Show unit information in __repr__ for datetime64("NaT")#
When a datetime64 object is “Not a Time” (NaT), its __repr__ method now
includes the time unit of the datetime64 type. This makes it consistent with
the behavior of a timedelta64 object.
(gh-29396)
numpy.finfo Refactor#
The numpy.finfo class has been completely refactored to obtain floating-point
constants directly from C compiler macros rather than deriving them at runtime.
This provides better accuracy, platform compatibility and corrected
several attribute calculations:
Constants like
eps,min,max,smallest_normal, andsmallest_subnormalnow come directly from standard C macros (FLT_EPSILON,DBL_MIN, etc.), ensuring platform-correct values.The deprecated
MachArruntime discovery mechanism has been removed.Derived attributes have been corrected to match standard definitions:
machepandnegepnow useint(log2(eps));nexpaccounts for all exponent patterns;nmantexcludes the implicit bit; andminexpfollows the C standard definition.longdouble constants, Specifically
smallest_normalnow follows the C standard definitions as per respecitive platform.Special handling added for PowerPC’s IBM double-double format.
New test suite added in
test_finfo.pyto validate allfinfoproperties against expected machine arithmetic values for float16, float32, and float64 types.
(gh-29836)
Multiple axes are now supported in numpy.trim_zeros#
The axis argument of numpy.trim_zeros now accepts a sequence; for example
np.trim_zeros(x, axis=(0, 1)) will trim the zeros from a multi-dimensional
array x along axes 0 and 1. This fixes issue
gh‑29945 and was implemented
in pull request gh‑29947.
(gh-29947)
Performance improvements and changes#
Performance improvements to np.unique for string dtypes#
The hash-based algorithm for unique extraction provides an order-of-magnitude speedup on large string arrays. In an internal benchmark with about 1 billion string elements, the hash-based np.unique completed in roughly 33.5 seconds, compared to 498 seconds with the sort-based method – about 15× faster for unsorted unique operations on strings. This improvement greatly reduces the time to find unique values in very large string datasets.
(gh-28767)
Rewrite of np.ndindex using itertools.product#
The numpy.ndindex function now uses itertools.product internally,
providing significant improvements in performance for large iteration spaces,
while maintaining the original behavior and interface.
For example, for an array of shape (50, 60, 90) the NumPy ndindex
benchmark improves performance by a factor 5.2.
(gh-29165)
Performance improvements to np.unique for complex dtypes#
The hash-based algorithm for unique extraction now also supports complex dtypes, offering noticeable performance gains.
In our benchmarks on complex128 arrays with 200,000 elements, the hash-based approach was about 1.4–1.5× faster than the sort-based baseline when there were 20% of unique values, and about 5× faster when there were 0.2% of unique values.
(gh-29537)
Changes#
Multiplication between a string and integer now raises OverflowError instead of MemoryError if the result of the multiplication would create a string that is too large to be represented. This follows Python’s behavior.
(gh-29060)
unique_values for string dtypes may return unsorted data#
np.unique now supports hash‐based duplicate removal for string dtypes. This enhancement extends the hash-table algorithm to byte strings (‘S’), Unicode strings (‘U’), and the experimental string dtype (‘T’, StringDType). As a result, calling np.unique() on an array of strings will use the faster hash-based method to obtain unique values. Note that this hash-based method does not guarantee that the returned unique values will be sorted. This also works for StringDType arrays containing None (missing values) when using equal_nan=True (treating missing values as equal).
(gh-28767)
Modulate dispatched x86 CPU features#
IMPORTANT: The default setting for cpu-baseline` on x86 has been raised to x86-64-v2 microarchitecture. This can be changed to none during build time to support older CPUs, though SIMD optimizations for pre-2009 processors are no longer maintained.
NumPy has reorganized x86 CPU features into microarchitecture-based groups instead of individual features, aligning with Linux distribution standards and Google Highway requirements.
Key changes:
* Replaced individual x86 features with microarchitecture levels: X86_V2, X86_V3, and X86_V4
* Raised the baseline to X86_V2
* Improved - operator behavior to properly exclude successor features that imply the excluded feature
* Added meson redirections for removed feature names to maintain backward compatibility
* Removed compiler compatibility workarounds for partial feature support (e.g., AVX512 without mask operations)
* Removed legacy AMD features (XOP, FMA4) and discontinued Intel Xeon Phi support
New Feature Group Hierarchy:
Name |
Implies |
Includes |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
These groups correspond to CPU generations:
X86_V2: x86-64-v2 microarchitectures (CPUs since 2009)X86_V3: x86-64-v3 microarchitectures (CPUs since 2015)X86_V4: x86-64-v4 microarchitectures (AVX-512 capable CPUs)AVX512_ICL: Intel Ice Lake and similar CPUsAVX512_SPR: Intel Sapphire Rapids and newer CPUs
Note
On 32-bit x86, cx16 is excluded from X86_V2.
Documentation has been updated with details on using these new feature groups with the current meson build system.
(gh-28896)
Fix bug in matmul for non-contiguous out kwarg parameter#
In some cases, if out was non-contiguous, np.matmul would cause
memory corruption or a c-level assert. This was new to v2.3.0 and fixed in v2.3.1.
(gh-29179)
__array_interface__ with NULL pointer changed#
The array interface now accepts NULL pointers (NumPy will do
its own dummy allocation, though).
Previously, these incorrectly triggered an undocumented
scalar path.
In the unlikely event that the scalar path was actually desired,
you can (for now) achieve the previous behavior via the correct
scalar path by not providing a data field at all.
(gh-29338)
unique_values for complex dtypes may return unsorted data#
np.unique now supports hash‐based duplicate removal for complex dtypes. This enhancement extends the hash‐table algorithm to all complex types (‘c’), and their extended precision variants. The hash‐based method provides faster extraction of unique values but does not guarantee that the result will be sorted.
(gh-29537)
Sorting kind='heapsort' now maps to kind='quicksort'#
It is unlikely that this change will be noticed, but if you do see a change in execution time or unstable argsort order, that is likely the cause. Please let us know if there is a performance regression. Congratulate us if it is improved :)
(gh-29642)
numpy.typing.DTypeLike no longer accepts None#
The type alias numpy.typing.DTypeLike no longer accepts None. Instead of
dtype: DTypeLike = None
it should now be
dtype: DTypeLike | None = None
instead.
(gh-29739)
The npymath and npyrandom libraries now have a .lib rather than a
.a file extension on win-arm64, for compatibility for building with MSVC and
setuptools. Please note that using these static libraries is discouraged
and for existing projects using it, it’s best to use it with a matching
compiler toolchain, which is clang-cl on Windows on Arm.
(gh-29750)