NumPy 2.4.0 发行说明#

NumPy 2.4.0 版本继续致力于改进 Python 的 free threaded 支持、用户自定义 dtype 的实现以及类型注解。其中还包括许多已过期的弃用项和错误修复。

此版本支持 Python 3.11-3.14。

亮点#

除了类型注解和 same_value 关键字参数外,2.4 版本的主要亮点对下游开发者更有价值。它们将有助于实现新的用户自定义 dtype。

  • 大量类型注解得到改进。特别是,运行时签名自省功能得到增强。

  • 新增 casting 关键字参数 'same_value',用于按值进行类型转换。

  • 新增 PyUFunc_AddLoopsFromSpec 函数,可用于使用 ArrayMethod API 添加用户自定义排序循环。

  • 新增 __numpy_dtype__ 协议。

弃用#

设置 strides 属性已弃用#

设置 strides 属性现已弃用,因为如果数组被共享,尤其是被多个线程共享,则修改数组是不安全的。作为替代方案,您可以使用以下方法创建新的视图(无复制):

  • np.lib.stride_tricks.strided_window_view(如果适用),

  • np.lib.stride_tricks.as_strided(通用情况),

  • np.ndarray 构造函数(其中 buffer 是原始数组),以实现轻量级版本。

(gh-28925)

np.maximumnp.minimum 的位置 out 参数已弃用#

将输出数组 out 作为位置参数传递给 numpy.maximumnumpy.minimum 已弃用。例如,np.maximum(a, b, c) 将会发出弃用警告,因为 c 被视为输出缓冲区而不是第三个输入。

始终通过关键字形式传递输出,例如 np.maximum(a, b, out=c)。这样可以明确意图并简化类型注解。

(gh-29052)

调用 np.dtype() 时,align= 必须作为布尔值传递#

创建新的 dtype 时,如果 align= 不是布尔值,将发出 VisibleDeprecationWarning。这主要是为了防止意外地将子数组的 align 标志传递进去,而该标志在此处没有效果,例如 np.dtype("f8", 3) 而非 np.dtype(("f8", 3))。强烈建议始终将 align= 作为关键字参数传递。

(gh-29301)

断言和警告控制工具已弃用#

np.testing.assert_warnsnp.testing.suppress_warnings 已弃用。请改用 warnings.catch_warningswarnings.filterwarningspytest.warnspytest.filterwarnings

(gh-29550)

np.fix 即将弃用#

函数 numpy.fix 将在未来的版本中弃用。建议使用 numpy.trunc,因为它提供了截断小数部分到整数部分的功能。静态类型检查器可能已报告 numpy.fix 使用的警告。

(gh-30168)

原地修改 ndarray.shape 即将弃用#

直接设置 ndarray.shape 属性将在未来的版本中弃用。与其原地修改 shape,不如建议使用 numpy.reshape 函数。静态类型检查器可能已报告对 ndarray.shape 赋值的警告。

(gh-30282)

弃用 numpy.lib.user_array.container#

numpy.lib.user_array.container 已弃用,将在未来的版本中移除。

(gh-30284)

已过期的弃用#

移除了已弃用的 MachAr 运行时发现机制。#

(gh-29836)

尝试将 ndim > 0 的数组转换为标量时,引发 TypeError#

ndim > 0 的数组转换为标量在 NumPy 1.25 中已弃用。现在,尝试这样做会引发 TypeError。请确保在执行此操作之前从数组中提取单个元素。

(gh-29841)

移除了 numpy.linalg.linalg 和 numpy.fft.helper#

以下内容在 NumPy 2.0 中已弃用,现已移至私有模块

  • numpy.linalg.linalg 请改用 numpy.linalg

  • numpy.fft.helper 请改用 numpy.fft

(gh-29909)

从 quantile 和 percentile 函数中移除了 interpolation 参数#

interpolation 参数在 NumPy 1.22.0 中已弃用,并已从以下函数中移除:

  • numpy.percentile

  • numpy.nanpercentile

  • numpy.quantile

  • numpy.nanquantile

请改用 method 参数。

(gh-29973)

移除了 numpy.in1d#

numpy.in1d 在 NumPy 2.0 中已弃用,现在已移除,取而代之的是 numpy.isin

(gh-29978)

移除了 numpy.ndindex.ndincr()#

ndindex.ndincr() 方法在 NumPy 1.20 中已弃用,现已移除;请改用 next(ndindex)

(gh-29980)

numpy.save 中移除了 fix_imports 参数#

fix_imports 参数在 NumPy 2.1.0 中已弃用,现已移除。该标志自 NumPy 1.17 起就被忽略,并且仅用于支持加载 Python 2 中写入的 Python 3 文件。

(gh-29984)

移除了四个未文档化的 ndarray.ctypes 方法#

已移除 ndarray.ctypes 对象的四个未文档化的方法

  • _ctypes.get_data()(请改用 _ctypes.data

  • _ctypes.get_shape()(请改用 _ctypes.shape

  • _ctypes.get_strides()(请改用 _ctypes.strides

  • _ctypes.get_as_parameter()(请改用 _ctypes._as_parameter_

这些方法自 NumPy 1.21 起已弃用。

(gh-29986)

numpy.reshape 中移除了 newshape 参数#

newshape 参数在 NumPy 2.1.0 中已弃用,并已从 numpy.reshape 中移除。在较新版本的 NumPy 中,请按位置传递或使用 shape=

(gh-29994)

移除了已弃用的函数和参数#

以下长期弃用的 API 已被移除

  • numpy.trapz — 自 NumPy 2.0(2023-08-18)起已弃用。请改用 numpy.trapezoidscipy.integrate 函数。

  • disp 函数 — 自 2.0 版本起已弃用,不再可用。请改用您自己的打印函数。

  • numpy.corrcoef 中的 biasddof 参数 — 自 NumPy 1.10 起这些参数已无效。

(gh-29997)

numpy.ma.mrecords.fromtextfile() 中移除了 delimitor 参数#

delimitor 参数在 NumPy 1.22.0 中已弃用,并已从 numpy.ma.mrecords.fromtextfile() 中移除。请改用 delimiter

(gh-30021)

numpy.array2stringnumpy.sum 的弃用最终确定#

以下长期弃用的 API 已被移除或转换为错误

  • style 参数已从 numpy.array2string 中移除。自 Numpy 1.14.0 起,此参数一直无效。其后的所有参数,如 formatter,现已变为仅限关键字参数。

  • 直接对生成器对象调用 np.sum(generator) 现在会引发 TypeError。此行为在 NumPy 1.15.0 中已弃用。请改用 np.sum(np.fromiter(generator)) 或 Python 的内置 sum 函数。

(gh-30068)

兼容性说明#

  • NumPy 的 C 扩展模块已开始使用 PEP 489 定义的多阶段初始化。作为此过程的一部分,已添加了新的显式检查,确保每个此类模块在每个 Python 进程中仅导入一次。这带来了一个副作用,即从 sys.modules 中删除 numpy 并重新导入它现在会因 ImportError 而失败。虽然这以前不会引发错误,但它一直是不安全且具有意外副作用的操作。

    (gh-29030)

  • numpy.round 现在始终返回副本。以前,对于 decimals >= 0 的整数输入,它会返回一个视图,而在所有其他情况下返回一个副本。此更改使 roundceilfloortrunc 保持一致。

    (gh-29137)

  • 类型检查器将不再接受使用 start 作为关键字参数调用 numpy.arange。此更改是为了与 Array API 标准兼容。在运行时,仍然可以使用 start 作为关键字参数来调用 numpy.arange

    (gh-30147)

  • 宏 NPY_ALIGNMENT_REQUIRED 已被移除。该宏定义在 npy_cpu.h 文件中,因此可能被视为半公开。事实证明,对于现代编译器和硬件,对齐几乎总是必需的,因此 NumPy 不再使用该宏。不太可能有人使用它,但您可能希望使用 -Wundef 标志或等效选项进行编译以确保安全。

    (gh-29094)

C API 更改#

NPY_SORTKIND 枚举已通过新变量得到增强#

如果您正在使用 PyArray_SortPyArray_ArgSort,则此项会有所帮助。我们已更改 NPY_SORTKIND 枚举中旧名称的语义,并添加了新名称。更改是向后兼容的,无需重新编译。新名称包括:

  • NPY_SORT_DEFAULT – 默认排序(与 NPY_QUICKSORT 值相同)

  • NPY_SORT_STABLE – 排序必须是稳定的(与 NPY_MERGESORT 值相同)

  • NPY_SORT_DESCENDING – 排序必须是降序的

语义上的变化是,当使用 NPY_HEAPSORT 时,它被映射到 NPY_QUICKSORT。请注意,NPY_SORT_DESCENDING 尚未实现。

(gh-29642)

用于 DType 常量检索的新 NPY_DT_get_constant 插槽#

DType API 已添加了新的插槽 NPY_DT_get_constant,允许 dtype 实现提供常量值,如机器限制和特殊值。插槽函数签名如下:

int get_constant(PyArray_Descr *descr, int constant_id, void *ptr)

它在成功时返回 1,如果常量不可用则返回 0,在出错时返回 -1。该函数始终在持有 GIL 的情况下调用,并且可能会写入未对齐的内存。

整数常量(标记为 1 << 16 位)返回 npy_intp 值,而浮点常量返回 dtype 的本机类型的值。

实现这一点可用于用户 DType 提供 numpy.finfo 值。

(gh-29836)

C API 中已添加了一个新的便利函数 PyUFunc_AddLoopsFromSpecs#

此函数允许使用 PyUFunc_LoopSlot 结构体的 NULL 终止数组一次添加多个 ufunc 循环。它允许使用新的 ArrayMethod API 注册排序和 argsort 循环。

(gh-29900)

新功能#

  • np.size 接受多个轴。

    (gh-29240)

  • numpy.pad 扩展为接受字典作为 pad_width 参数。

    (gh-29273)

'same_value' 用于按值进行类型转换#

casting 关键字参数现在有一个 'same_value' 选项,它会检查实际值是否可以进行往返类型转换而不会改变值。目前它仅在 ndarray.astype 中实现。如果数组中的任何值会因类型转换而改变(包括浮点数的舍入或整数的溢出),这将引发 ValueError

(gh-29129)

StringDTypenumpy.ma.MaskedArray 中支持 fill_value#

当使用可变宽度 StringDType(类型为 'T')时,掩码数组现在接受并保留 Python str 作为其 fill_value,包括通过切片和视图。默认值为 'N/A',并且可以通过任何有效字符串进行覆盖。这修复了 issue gh‑29421,并在 pull request gh‑29423 中实现。

(gh-29423)

numpy.array 添加 ndmax 选项#

现在为 numpy.array 提供了 ndmax 选项。它显式限制了从嵌套序列创建的最大维度数。

这在创建具有 dtype=object 的列表类对象数组时特别有用。默认情况下,NumPy 会递归遍历所有嵌套级别以创建最高维度的数组,但当意图是保留嵌套结构作为对象时,这种行为可能不被需要。ndmax 参数提供了对这种递归深度的显式控制。

# 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)

使用 where 但不使用 out 时发出警告#

现在,当 ufunc 在没有 out 位置参数或关键字参数的情况下使用 where 掩码调用时,会发出警告。这种用法容易让用户感到困惑,他们期望在掩码为 False 的输出位置获得某些值(ufunc 不会触及那些位置)。可以通过使用 out=None 来抑制警告。

(gh-29813)

DType 的排序和 argsort 支持 ArrayMethod API#

用户定义的 dtype 现在可以使用 ArrayMethod API 实现自定义排序和 argsort。此机制可用于替代未来可能弃用的 PyArray_ArrFuncs 插槽。

排序和 argsort 方法通过将实现这些操作的 arraymethod spec 传递给新的 PyUFunc_AddLoopsFromSpecs 函数来注册。有关详细信息,请参阅 ArrayMethod API 文档。

(gh-29900)

新的 __numpy_dtype__ 协议#

NumPy 现在有了一个新的 __numpy_dtype__ 协议。当通过 np.dtype(obj) 或任何 dtype= 参数转换为 NumPy dtype 时,NumPy 将会检查此属性。

鼓励下游项目为所有类似 dtype 的对象实现此协议,这些对象以前可能使用返回 NumPy dtype 的 .dtype 属性。我们预计未来会弃用 .dtype,以防止将具有 .dtype 属性的类数组对象解释为 dtype。如果需要,您可以实现 __numpy_dtype__ 来确保更早的警告或错误(如果找到此属性,则会忽略 .dtype)。

(gh-30179)

改进#

修复 flatiter 索引的边缘情况#

flatiter 对象现在与 ndarray 共享相同的索引准备逻辑,确保行为一致并修复了几个先前接受或误解无效索引的问题。

关键修复和改进

  • 更严格的索引验证

    • 布尔非数组索引,如 arr.flat[[True, True]],以前被错误地视为 arr.flat[np.array([1, 1], dtype=int)]。现在它们会引发索引错误。请注意,与迭代器形状匹配的索引在未来预期不会引发错误,并将作为常规布尔索引进行处理。如果您想匹配该行为,请使用 np.asarray(<index>)

    • 浮点非数组索引也曾被转换为整数,并被错误地视为 arr.flat[np.array([1.0, 1.0], dtype=int)]。此行为现已弃用,将在未来的版本中移除。

    • 0 维布尔索引,如 arr.flat[True],也已弃用,将在未来的版本中移除。

  • 一致的错误类型

    某些无效的 flatiter 索引以前会引发 ValueError,现在会正确地引发 IndexError,与 ndarray 的行为一致。

  • 改进的错误消息

    不支持的索引操作的错误消息现在提供了更详细的信息,包括明确列出有效的索引类型,而不是通用的 IndexError: unsupported index operation

(gh-28590)

改进了 np.quantile 中的错误处理#

np.quantile 现在如果出现以下情况会引发错误:

  • 所有权重都为零

  • 至少一个权重为 np.nan

  • 至少一个权重为 np.inf

(gh-28595)

改进了 assert_array_compare 的错误消息#

assert_array_compare 生成的错误消息(由 assert_allcloseassert_array_less 等函数使用)现在还包括了断言失败的索引信息。

(gh-29112)

显示 datetime64("NaT")__repr__ 中的单位信息#

datetime64 对象是“非时间”(NaT)时,其 __repr__ 方法现在包含 datetime64 类型的单位信息。这使其与 timedelta64 对象的行为一致。

(gh-29396)

标量计算性能提升#

标量计算速度提高了约 6 倍,对于仅接受一个输入的 ufunc(如 np.sin(scalar)),将速度差异从 19 倍减小到 3 倍(数组的速度保持不变)。

(gh-29819)

numpy.finfo 重构#

numpy.finfo 类已完全重构,以直接从 C 编译器宏获取浮点常量,而不是在运行时推导。这提供了更好的准确性、平台兼容性,并纠正了几个属性计算错误。

  • 常量,如 epsminmaxsmallest_normalsmallest_subnormal,现在直接来自标准 C 宏(FLT_EPSILONDBL_MIN 等),确保了平台正确的数值。

  • 已移除已弃用的 MachAr 运行时发现机制。

  • 派生属性已得到更正,以匹配标准定义:machepnegep 现在使用 int(log2(eps))nexp 包含所有指数模式;nmant 排除隐式位;minexp 遵循 C 标准定义。

  • longdouble 常量,特别是 smallest_normal,现在遵循相应平台上的 C 标准定义。

  • 为 PowerPC 的 IBM double-double 格式添加了特殊处理。

  • test_finfo.py 中添加了新的测试套件,用于针对 float16、float32 和 float64 类型验证所有 finfo 属性与预期的机器算术值。

(gh-29836)

numpy.trim_zeros 现在支持多个轴#

numpy.trim_zerosaxis 参数现在接受一个序列;例如,np.trim_zeros(x, axis=(0, 1)) 将沿轴 0 和 1 修剪多维数组 x 中的零。这修复了 issue gh‑29945,并在 pull request gh‑29947 中实现。

(gh-29947)

运行时签名自省支持已得到显著改进#

许多以前传递给 inspect.signature() 时会引发 ValueError 的 NumPy 函数、类和方法现在可以返回有意义的签名。这改善了 NumPy API 的运行时类型检查、IDE 自动完成、文档生成和运行时自省功能。

总共有三百多个类和函数得到了更新,包括但不限于核心类,如 ndarray, generic, dtype, ufunc, broadcast, nditer 等,ndarray 的大多数方法和标量类型,数组构造函数(array, empty, arange, fromiter 等),所有 ufuncs,以及许多其他常用函数,包括 dot, concat, where, bincount, can_cast,等等。

(gh-30208)

性能改进和更改#

改进 np.unique 对字符串 dtype 的性能#

用于提取唯一值的基于哈希的算法在大型字符串数组上提供了数量级的加速。在拥有约 10 亿个字符串元素的内部基准测试中,基于哈希的 np.unique 耗时约 33.5 秒,而基于排序的方法耗时 498 秒——对于字符串的未排序唯一值操作,速度提高了约 15 倍。这一改进大大缩短了在超大型字符串数据集中查找唯一值所需的时间。

(gh-28767)

使用 itertools.product 重写 np.ndindex#

numpy.ndindex 函数现在内部使用 itertools.product,为大型迭代空间提供了显著的性能改进,同时保持了原始行为和接口。例如,对于形状为 (50, 60, 90) 的数组,NumPy 的 ndindex 基准测试将性能提高了 5.2 倍。

(gh-29165)

改进 np.unique 对复数 dtype 的性能#

用于提取唯一值的基于哈希的算法现在也支持复数 dtype,提供了可观的性能提升。

在我们对具有 200,000 个元素的 complex128 数组进行的基准测试中,当唯一值占 20% 时,基于哈希的方法比基于排序的方法快约 1.4-1.5 倍,而当唯一值占 0.2% 时,则快约 5 倍。

(gh-29537)

更改#

  • 字符串与整数的乘法现在如果乘积结果会创建一个过大的字符串,将引发 OverflowError 而不是 MemoryError。这遵循了 Python 的行为。

    (gh-29060)

  • 改进了 np.quantilenp.percentile 对 16 位和 32 位浮点输入数据的精度。

    (gh-29105)

字符串 dtype 的 unique_values 可能返回未排序的数据#

np.unique 现在支持对字符串 dtype 进行基于哈希的去重。此增强功能将哈希表算法扩展到字节字符串(‘S’)、Unicode 字符串(‘U’)和实验性的字符串 dtype(‘T’,StringDType)。因此,在字符串数组上调用 np.unique() 将使用更快的基于哈希的方法来获取唯一值。请注意,此基于哈希的方法不保证返回的唯一值是排序的。当使用 equal_nan=True(将缺失值视为相等)时,它也适用于包含 None(缺失值)的 StringDType 数组。

(gh-28767)

调制分派的 x86 CPU 功能#

重要提示:x86 上的 cpu-baseline 的默认设置已提高到 x86-64-v2 微架构。这可以在构建时更改为 none 以支持旧的 CPU,但不再维护 2009 年之前的处理器的 SIMD 优化。

NumPy 已将 x86 CPU 功能从单个功能重新组织为基于微架构的组,以符合 Linux 发行版标准和 Google Highway 要求。

主要变化

  • 将单个 x86 功能替换为微架构级别:X86_V2X86_V3X86_V4

  • 将基线提高到 X86_V2

  • 改进了 - 运算符的行为,以正确排除隐含被排除功能的后继功能

  • 为已删除的功能名称添加了 meson 重定向,以维护向后兼容性

  • 移除了对部分功能支持的编译器兼容性解决方案(例如,没有掩码操作的 AVX512)

  • 移除了旧的 AMD 功能(XOP, FMA4)并停止支持 Intel Xeon Phi

新的功能组层次结构

名称

隐含

包含

X86_V2

SSE SSE2 SSE3 SSSE3 SSE4_1 SSE4_2 POPCNT CX16 LAHF

X86_V3

X86_V2

AVX AVX2 FMA3 BMI BMI2 LZCNT F16C MOVBE

X86_V4

X86_V3

AVX512F AVX512CD AVX512VL AVX512BW AVX512DQ

AVX512_ICL

X86_V4

AVX512VBMI AVX512VBMI2 AVX512VNNI AVX512BITALG AVX512VPOPCNTDQ AVX512IFMA VAES GFNI VPCLMULQDQ

AVX512_SPR

AVX512_ICL

AVX512FP16

这些组对应于 CPU 代

  • X86_V2:x86-64-v2 微架构(2009 年以来的 CPU)

  • X86_V3:x86-64-v3 微架构(2015 年以来的 CPU)

  • X86_V4:x86-64-v4 微架构(支持 AVX-512 的 CPU)

  • AVX512_ICL:Intel Ice Lake 及类似 CPU

  • AVX512_SPR:Intel Sapphire Rapids 及更新的 CPU

注意

在 32 位 x86 上,cx16 已从 X86_V2 中排除。

文档已更新,详细介绍了如何使用这些新的功能组与当前的 meson 构建系统。

(gh-28896)

修复 matmul 中非连续 out 关键字参数的错误#

在某些情况下,如果 out 非连续,np.matmul 会导致内存损坏或 C 级断言。这是 v2.3.0 新增的,已在 v2.3.1 中修复。

(gh-29179)

具有 NULL 指针的 __array_interface__ 已更改#

数组接口现在接受 NULL 指针(NumPy 将执行自己的虚拟分配)。以前,这些会错误地触发一个未记录的标量路径。在极少数情况下,如果确实需要标量路径,您可以通过不提供 data 字段来(暂时)通过正确的标量路径实现以前的行为。

(gh-29338)

复数 dtype 的 unique_values 可能返回未排序的数据#

np.unique 现在支持对复数 dtype 进行基于哈希的去重。此增强功能将哈希表算法扩展到所有复数类型(‘c’)及其扩展精度变体。基于哈希的方法提供了更快的唯一值提取,但不保证结果已排序。

(gh-29537)

排序 kind='heapsort' 现在映射到 kind='quicksort'#

这项更改不太可能引起注意,但如果您看到执行时间或 argsort 顺序不稳定,那很可能是原因。如果您遇到性能回归,请告知我们。如果性能有所提升,请祝贺我们 :)

(gh-29642)

numpy.typing.DTypeLike 不再接受 None#

类型别名 numpy.typing.DTypeLike 不再接受 None。使用

dtype: DTypeLike = None

现在应该使用

dtype: DTypeLike | None = None

代替。

(gh-29739)

对于 win-arm64,npymathnpyrandom 库现在具有 .lib 而不是 .a 文件扩展名,以便与 MSVC 和 setuptools 兼容。请注意,不鼓励使用这些静态库,对于已在使用它的现有项目,最好与匹配的编译器工具链一起使用,即 Windows on Arm 上的 clang-cl

(gh-29750)