NumPy 1.25.0 发布说明#

NumPy 1.25.0 的发布继续了我们在改进 dtype 的处理和提升、提高执行速度以及澄清文档方面所做的持续工作。还进行了大量工作来为未来的 NumPy 2.0.0 版本做准备,这导致了大量新的和过时的弃用。亮点包括:

  • 支持 MUSL,现在有 MUSL 轮子。

  • 支持 Fujitsu C/C++ 编译器。

  • einsum 现在支持对象数组

  • 支持原地矩阵乘法(@=)。

我们将在 Python 3.12 发布时发布 NumPy 1.26。这是必需的,因为 distutils 已被 Python 3.12 弃用,我们将改用 meson 进行未来的构建。下一个主线版本将是 NumPy 2.0.0。我们计划 2.0 系列仍将支持基于早期 NumPy 版本构建的下游项目。

此版本支持的 Python 版本为 3.9-3.11。

弃用#

  • np.core.MachAr 已弃用。它是私有 API。在 np.core 中定义的名称通常应被视为私有。

    (gh-22638)

  • np.finfo(None) 已弃用。

    (gh-23011)

  • np.round_ 已弃用。请改用 np.round

    (gh-23302)

  • np.product 已弃用。请改用 np.prod

    (gh-23314)

  • np.cumproduct 已弃用。请改用 np.cumprod

    (gh-23314)

  • np.sometrue 已弃用。请改用 np.any

    (gh-23314)

  • np.alltrue 已弃用。请改用 np.all

    (gh-23314)

  • 只有 ndim-0 数组才被视为标量。NumPy 过去会将所有大小为 1 的数组(例如 np.array([3.14]))视为标量。将来,这仅限于 ndim 为 0 的数组(例如 np.array(3.14))。以下表达式将报告弃用警告:

    a = np.array([3.14])
    float(a)  # better: a[0] to get the numpy.float or a.item()
    
    b = np.array([[3.14]])
    c = numpy.random.rand(10)
    c[0] = b  # better: c[0] = b[0, 0]
    

    (gh-10615)

  • np.find_common_type 已弃用。numpy.find_common_type 已弃用,其用法应替换为 numpy.result_typenumpy.promote_types。大多数用户将 find_common_type 的第二个 scalar_types 参数保留为 [],在这种情况下,np.result_typenp.promote_types 都更快、更健壮。在使用 scalar_types 时,主要区别在于替换会故意将非本机字节序转换为本机字节序。此外,find_common_type 返回 object dtype 而不是失败提升。这会导致输入不全为数值时出现差异。重要的是,这也适用于例如 timedelta/datetime,对于这些类型,NumPy 的提升规则目前有时会令人惊讶。

    scalar_types 参数不是 [] 时,情况会更复杂。在大多数情况下,使用 np.result_type 并传递 Python 值 00.00j 的结果与在 scalar_types 中使用 intfloatcomplex 相同。

    scalar_types 被构造时,np.result_type 是正确的替换,并且它可以传递标量值,例如 np.float32(0.0)。传递非 0 值可能会导致值检查行为(np.find_common_type 从未这样做过,NEP 50 未来可能会更改)。在这种情况下,最可能的行为变化是当数组类型为有符号整数而标量类型为无符号时。

    如果您不确定如何替换 scalar_types 的用法,或者当非数值 dtype 可能性很高时,请随时在 NumPy 问题跟踪器中提问寻求帮助。

    (gh-22539)

已过期的弃用#

  • np.core.macharnp.finfo.machar 已被移除。

    (gh-22638)

  • 当 dtype 不是数值类型时(并且正数未定义),+arr 现在将引发错误。

    (gh-22998)

  • 现在必须将一个序列传递给堆叠函数系列(stackvstackhstackdstackcolumn_stack)。

    (gh-23019)

  • np.clip 现在默认为同类型转换。在 NumPy 1.17 中,回退到不安全转换已被弃用。

    (gh-23403)

  • np.clip 现在将传播作为 minmax 传递的 np.nan 值。以前,标量 NaN 通常被忽略。这在 NumPy 1.17 中已被弃用。

    (gh-23403)

  • np.dual 子模块已被移除。

    (gh-23480)

  • NumPy 现在总是忽略类数组(定义了 array 协议之一)的序列行为。(弃用始于 NumPy 1.20)

    (gh-23660)

  • astypeasarray 等数组创建函数中,转换为子数组 dtype 时的细微 FutureWarning 现已最终确定。行为现在总是与将子数组 dtype 包装到单个字段中(之前是解决方法)相同。(自 NumPy 1.20 起为 FutureWarning)

    (gh-23666)

  • == 和 != 警告已最终确定。数组上的 == 和 != 运算符现在总是

    • 在比较时引发错误,例如当数组形状不兼容时(np.array([1, 2]) == np.array([1, 2, 3]))。

    • 当值根本无法比较时(例如,具有不同的 dtypes),返回一个全为 True 或全为 False 的数组。例如 np.array(["a"]) == np.array([1])

      这模仿了 Python 中比较不兼容类型(如 "a" == 1"a" != 1)时返回 FalseTrue 的行为。很长一段时间以来,这些行为都产生了 DeprecationWarningFutureWarning

    (gh-22707)

  • 已移除 Nose 支持。NumPy 于 2018 年切换到使用 pytest,而 nose 已经多年未维护。我们保留了 NumPy 的 nose 支持,以避免破坏可能正在使用它但尚未切换到 pytest 或其他测试框架的下游项目。随着 Python 3.12 的到来,未修补的 nose 将引发错误。是时候向前看了。

    已移除装饰器:

    • raises

    • slow

    • setastest

    • skipif

    • knownfailif

    • deprecated

    • parametrize

    • _needs_refcount

    这些不应与名称相似的 pytest 版本混淆,例如 pytest.mark.slow、pytest.mark.skipif、pytest.mark.parametrize。

    已移除函数:

    • Tester

    • import_nose

    • run_module_suite

    (gh-23041)

  • 已移除 numpy.testing.utils 包装器。自 2019 年以来,从 numpy.testing.utils 包装器导入已被弃用,包装器现已移除。所有导入都应直接从 numpy.testing 进行。

    (gh-23060)

  • 已移除禁用分发的环境变量。对 NUMPY_EXPERIMENTAL_ARRAY_FUNCTION 环境变量的支持已移除。此变量禁用使用 __array_function__ 的分发。

    (gh-23376)

  • 已移除 y= 作为 out= 的别名。 fixisposinfisneginf 函数允许使用 y= 作为(已弃用的) out= 的别名。这不再支持。

    (gh-23376)

兼容性说明#

  • busday_count 方法现在能正确处理 begindates 晚于 enddates 的情况。以前,enddates 被包含在内,尽管文档说明它总是被排除。

    (gh-23229)

  • 当使用 np.equalnp.not_equal 比较日期时间和 timedelta 时,NumPy 以前允许 casting="unsafe" 的比较。此操作现在会失败。使用 dtype 关键字参数强制输出 dtype 可以使操作成功,但不推荐这样做。

    (gh-22707)

  • 当使用 np.load 从文件句柄加载数据时,如果句柄位于文件末尾(当通过重复调用 np.load 读取多个数组时会发生这种情况),NumPy 以前会在 allow_pickle=False 时引发 ValueError,在 allow_pickle=True 时引发 OSError。现在,在这两种情况下都会引发 EOFError

    (gh-23105)

np.pad 配合 mode=wrap 使用 wrap 模式进行填充,填充值是原始数据的严格倍数#

基于早期版本 pad 代码且使用 mode="wrap" 的代码,当填充大小大于初始数组时,将返回不同的结果。

np.pad 配合 mode=wrap 现在始终使用原始数据的严格倍数填充空间,即使填充大小大于初始数组。

(gh-22575)

Cython 的 long_tulong_t 已移除#

long_tulong_tlonglong_tulonglong_t 的别名,并且具有混淆性(是 Python 2 的遗留)。此更改可能导致错误:

'long_t' is not a type identifier
'ulong_t' is not a type identifier

我们建议使用位大小的类型,例如 cnp.int64_tcnp.intp_t,后者在 32 位系统上为 32 位,在 64 位系统上为 64 位(这与索引最兼容)。如果需要 C long,请使用纯 longnpy_longcnp.int_t 也是 long(NumPy 的默认整数)。但是,在 64 位 Windows 上 long 是 32 位,我们可能希望在 NumPy 中也调整这一点。(如果您对此感到好奇,请随时联系 NumPy 开发人员。)

(gh-22637)

更改了传递给 ufunc 的错误 axes 参数的错误消息和类型#

传递给 ufunc(..., axes=[...])` 的错误 axes 值不正确时,错误消息和类型已更改。消息现在更能指示问题,如果值不匹配,将引发 AxisError。对于无效的输入类型,仍将引发 TypeError

(gh-22675)

定义了 __array_ufunc__ 的类数组在用作 where 时,可以覆盖 ufuncs#

如果 numpy.ufuncwhere 关键字参数是 numpy.ndarray 的子类,或者是一个定义了 numpy.class.__array_ufunc__ 的鸭子类型,那么它可以通过与输入和输出参数相同的机制来覆盖 ufunc 的行为。请注意,为了使此功能正常工作,where.__array_ufunc__ 实现必须解包 where 参数以将其传递给 ufunc 的默认实现,或者对于 numpy.ndarray 子类,在使用 super().__array_ufunc__ 之前。

(gh-23240)

默认情况下,针对 NumPy C API 进行编译现在是向后兼容的#

NumPy 现在默认公开 C API 的向后兼容子集。这使得 oldest-supported-numpy 的使用不再必要。库可以覆盖默认的最小版本以兼容使用

#define NPY_TARGET_VERSION NPY_1_22_API_VERSION

在包含 NumPy 之前,或者通过将等效的 -D 选项传递给编译器。NumPy 1.25 的默认值为 NPY_1_19_API_VERSION。由于 NumPy 1.19 C API 与 NumPy 1.16 相同,因此生成的程序在 C API 方面与 NumPy 1.16 兼容。此默认值将在未来的非错误修复版本中增加。您仍然可以针对旧版 NumPy 进行编译并在新版上运行。

有关更多详细信息,请参阅 对于下游包作者

(gh-23528)

新功能#

np.einsum 现在接受具有 object dtype 的数组#

代码路径将对对象 dtype 数组调用 Python 运算符,这与 np.dotnp.matmul 非常相似。

(gh-18053)

添加对原地矩阵乘法的支持#

现在可以通过 @= 运算符执行原地矩阵乘法。

>>> import numpy as np

>>> a = np.arange(6).reshape(3, 2)
>>> print(a)
[[0 1]
 [2 3]
 [4 5]]

>>> b = np.ones((2, 2), dtype=int)
>>> a @= b
>>> print(a)
[[1 1]
 [5 5]
 [9 9]]

(gh-21120)

添加了 NPY_ENABLE_CPU_FEATURES 环境变量#

用户现在可以通过指定 NPY_ENABLE_CPU_FEATURES 环境变量来选择仅在运行时启用一部分 CPU 功能。请注意,指定的这些功能必须在基线之外,因为基线功能始终假定存在。如果尝试启用 CPU 不支持或 NumPy 未构建的功能,将引发错误。

(gh-22137)

NumPy 现在有一个 np.exceptions 命名空间#

NumPy 现在有一个专用命名空间,可以访问大多数异常和警告。所有这些仍然可以在主命名空间中访问,尽管一些可能会在未来缓慢移动。这样做的主要原因是提高可发现性并添加未来的异常。

(gh-22644)

np.linalg 函数返回 NamedTuples#

返回元组的 np.linalg 函数现在返回 namedtuples。这些函数是 eig()eigh()qr()slogdet()svd()。在这些函数使用某些关键字参数(如 svd(compute_uv=False))返回非元组的情况下,返回类型保持不变。

(gh-22786)

np.char 中的字符串函数与 NEP 42 自定义 dtype 兼容#

表示 Unicode 字符串或字节字符串的自定义 dtype 现在可以传递给 np.char 中的字符串函数。

(gh-22863)

可以从字符串抽象 dtype 类创建字符串 dtype 实例#

现在可以创建一个带有大小的字符串 dtype 实例,而无需使用 dtype 的字符串名称。例如,type(np.dtype('U'))(8) 将创建一个等同于 np.dtype('U8') 的 dtype。此功能在编写处理字符串 dtype 类的通用代码时最有用。

(gh-22963)

现在支持 Fujitsu C/C++ 编译器#

已添加对 Fujitsu 编译器的支持。要使用 Fujitsu 编译器进行构建,请运行

python setup.py build -c fujitsu

现在支持 SSL2#

已添加对 SSL2 的支持。SSL2 是一个提供 OpenBLAS 兼容 GEMM 函数的库。要启用 SSL2,需要编辑 site.cfg 并使用 Fujitsu 编译器进行构建。请参阅 site.cfg.example。

(gh-22982)

改进#

NDArrayOperatorsMixin 指定它没有 __slots__#

NDArrayOperatorsMixin 类现在指定它不包含 __slots__,从而确保子类现在可以在 Python 中使用此功能。

(gh-23113)

修复复数零的幂#

对于复数,np.power 现在对于 0^{non-zero} 返回不同的结果。请注意,只有当指数的实部大于零时,该值才有定义。以前,除非虚部严格为零,否则会返回 NaN。返回值要么是 0+0j,要么是 0-0j

(gh-18535)

新的 DTypePromotionError#

NumPy 现在有一个新的 DTypePromotionError,当两个 dtypes 无法提升到共同的 dtype 时使用,例如

np.result_type("M8[s]", np.complex128)

引发此新异常。

(gh-22707)

np.show_config 使用来自 Meson 的信息#

构建和系统信息现在包含来自 Meson 的信息。np.show_config 现在有一个新的可选参数 mode 来帮助自定义输出。

(gh-22769)

修复了 np.ma.diff 在调用 prepend/append 参数时未保留掩码的问题#

使用 prepend 和/或 append 参数调用 np.ma.diff 现在返回一个 MaskedArray,并保留输入掩码。

以前,返回的是一个没有掩码的 MaskedArray

(gh-22776)

修正了 Cython 中 NumPy C API 的错误处理#

许多为 Cython 使用定义的 NumPy C 函数缺少正确的错误指示符,如 except -1except *。这些现在已被添加。

(gh-22997)

能够直接生成随机数生成器#

numpy.random.Generator.spawn 现在允许通过 numpy.random.SeedSequence.spawn 机制直接生成新的独立子生成器。numpy.random.BitGenerator.spawn 对底层位生成器也执行相同的操作。

此外,numpy.random.BitGenerator.seed_seq 现在可以直接访问用于初始化位生成器的种子序列。这允许例如

seed = 0x2e09b90939db40c400f8f22dae617151
rng = np.random.default_rng(seed)
child_rng1, child_rng2 = rng.spawn(2)

# safely use rng, child_rng1, and child_rng2

以前,这很难做到,而不显式传递 SeedSequence。有关更多信息,请参阅 numpy.random.SeedSequence

(gh-23195)

numpy.logspace 现在支持非标量 base 参数#

numpy.logspacebase 参数现在可以是类数组,只要它与 startstop 参数可广播。

(gh-23275)

np.ma.dot() 现在支持非 2D 数组#

以前 np.ma.dot() 仅在 ab 均为 2D 时才有效。现在它与 np.dot() 一样,对于非 2D 数组也有效。

(gh-23322)

在 .npz 文件的 repr 中显式显示键#

NpzFile 在打印时会显示加载的 .npz 文件的键。

>>> npzfile = np.load('arr.npz')
>>> npzfile
NpzFile 'arr.npz' with keys arr_0, arr_1, arr_2, arr_3, arr_4...

(gh-23357)

NumPy 现在在 np.dtypes 中公开 DType 类#

新的 numpy.dtypes 模块现在公开 DType 类,并将包含未来的 dtype 相关功能。大多数用户应无需直接使用这些类。

(gh-23358)

在保存到 .npy 或 .npz 文件之前删除 dtype 元数据#

目前,包含带有元数据的 dtype 表的 *.npy 文件无法读回。现在,np.savenp.savez 在保存前会删除元数据。

(gh-23371)

numpy.lib.recfunctions.structured_to_unstructured 在更多情况下返回视图#

structured_to_unstructured 现在在字段之间的步幅恒定时返回视图。之前,字段之间的填充或反转的字段会导致复制。此更改仅适用于 ndarraymemmaprecarray。对于所有其他数组子类,行为保持不变。

(gh-23652)

有符号和无符号整数始终正确比较#

当 NumPy 中混合 uint64int64 时,NumPy 通常会将两者提升为 float64。这种行为可能存在争议,但在比较 ==<= 时会令人困惑,因为返回的结果可能不正确,但由于结果是布尔值,转换是隐藏的。NumPy 现在将通过避免转换为 float 来为这些情况返回正确的结果。

(gh-23713)

性能改进和更改#

在启用 AVX-512 的处理器上,np.argsort 更快#

在支持 AVX-512 指令集的处理器上,32 位和 64 位快速排序算法的 np.argsort 可获得高达 6 倍的速度提升。

感谢 Intel 公司 赞助此项工作。

(gh-23707)

在支持 AVX-512 的处理器上,更快的 np.sort#

在支持 AVX-512 指令集的处理器上,16 位和 64 位数据类型的快速排序可获得高达 15 倍和 9 倍的速度提升。

感谢 Intel 公司 赞助此项工作。

(gh-22315)

__array_function__ 机制现已快得多#

NumPy 中大多数函数的开销现已减小,尤其是在使用关键字参数时。此更改显著加快了许多简单函数调用的速度。

(gh-23020)

ufunc.at 可以快得多#

通用的 ufunc.at 最多可快 9 倍。此速度提升的条件是

  • 操作数对齐

  • 无类型转换

如果具有适当的索引循环的一维参数(符合上述条件)的 ufunc,ufunc.at 最多可快 60 倍(额外 7 倍的速度提升)。已将适当的索引循环添加到 addsubtractmultiplyfloor_dividemaximumminimumfmaxfmin 中。

内部逻辑类似于常规 ufunc 的逻辑,后者也有快速路径。

感谢 D. E. Shaw Group 赞助此项工作。

(gh-23136)

NpzFile 的成员资格测试更快#

NpzFile 的成员资格测试成功时将不再解压缩存档。

(gh-23661)

更改#

使用某些标量值的 np.r_[]np.c_[]#

在极少数情况下,主要使用带标量值的 np.r_ 可能导致不同的结果。主要潜在更改如下面所示:

>>> np.r_[np.arange(5, dtype=np.uint8), -1].dtype
int16  # rather than the default integer (int64 or int32)
>>> np.r_[np.arange(5, dtype=np.int8), 255]
array([  0,   1,   2,   3,   4, 255], dtype=int16)

第二个示例返回

array([ 0,  1,  2,  3,  4, -1], dtype=int8)

第一个是由于带符号整数标量与无符号整数数组,而第二个是由于 255 不适合 int8,并且 NumPy 目前正在检查值以使其正常工作。(请注意,由于 NEP 50,第二个示例预计将来会发生变化;届时将引发错误。)

(gh-22539)

大多数 NumPy 函数都封装为 C 可调用项#

为了加速 __array_function__ 分派,大多数 NumPy 函数现在都封装为 C 可调用项,而不是真正的 Python 函数或 C 方法。它们仍然具有与以前相同的外观和感觉(如 Python 函数),这只会提高性能和用户体验(更干净的堆栈跟踪)。但是,如果此更改导致程序出现任何问题,请告知 NumPy 开发人员。

(gh-23020)

C++ 标准库使用#

NumPy 现在依赖 C++ 标准库进行构建,因为 numpy.core._multiarray_umath 扩展是与 C++ 链接器链接的。

(gh-23601)