NumPy 1.25.0 发布说明#

NumPy 1.25.0 版本继续进行改进数据类型处理和推广、提高执行速度以及澄清文档的工作.还进行了为未来的 NumPy 2.0.0 版本做准备的工作,导致大量新的和过期的弃用.亮点包括:

  • 对MUSL的支持,现在有MUSL的wheels.

  • 支持富士通 C/C++ 编译器.

  • 对象数组现在在 einsum 中得到支持

  • 支持就地矩阵乘法(@=).

我们将在 Python 3.12 发布时发布 NumPy 1.26.这是必需的,因为 Python 3.12 已经移除了 distutils,我们将切换到使用 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_type`` 和 np.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 的使用,或者在非数值 dtypes 可能出现时,请不要犹豫,打开一个 NumPy 问题寻求帮助.

    (gh-22539)

过时的弃用#

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

    (gh-22638)

  • +arr 现在会在 dtype 不是数值类型(且 positive 未定义)时引发错误.

    (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 现在总是忽略序列行为.(弃用从 NumPy 1.20 开始)

    (gh-23660)

  • astype 或数组创建函数(如 asarray)中转换为子数组数据类型时,``FutureWarning`` 的特殊情况现已最终确定.现在,行为始终与子数组数据类型被包装成单个字段时相同(这是之前的解决方法).(自 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 在比较不兼容类型时返回 FalseTrue 的行为,例如 "a" == 1"a" != 1.长期以来,这些会产生 DeprecationWarningFutureWarning.

    (gh-22707)

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

    Decorators removed:

    • raises

    • setastest

    • skipif

    • knownfailif

    • 已弃用

    • parametrize

    • _needs_refcount

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

    Functions removed:

    • 测试者

    • 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= 的别名已被移除.``fix``、isposinfisneginf 函数允许使用 y= 作为 out= 的(已弃用)别名.这不再受支持.

    (gh-23376)

兼容性说明#

  • busday_count 方法现在正确处理了 begindates 在时间上晚于 enddates 的情况.以前,即使文档说明 enddates 总是被排除的,它仍然被包含在内.

    (gh-23229)

  • 比较日期时间和时间增量时使用 np.equalnp.not_equal,numpy 之前允许在 casting="unsafe" 的情况下进行比较.现在这种操作会失败.使用 dtype kwarg 强制输出数据类型可以使操作成功,但我们不推荐这样做.

    (gh-22707)

  • 当使用 np.load 从一个文件句柄加载数据时,如果句柄在文件末尾,这种情况可能发生在通过反复调用 np.load 读取多个数组时,numpy 之前会在 allow_pickle=False 时引发 ValueError,在 allow_pickle=True 时引发 OSError.现在在这两种情况下都会引发 EOFError.

    (gh-23105)

np.pad 使用 mode=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_t 或使用 cnp.intp_t,它在32位系统上是32位,在64位系统上是64位(这最兼容索引).如果需要C long,请使用普通的 longnpy_long.``cnp.int_t`` 也是 long``(NumPy的默认整数).然而,``long 在64位Windows上是32位,我们可能希望在NumPy中调整这一点.(如果您对此感到好奇,请随时联系NumPy开发者.)

(gh-22637)

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

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

(gh-22675)

定义了 __array_ufunc__ 的类数组对象现在可以在用作 where 时覆盖通用函数(ufuncs)#

如果 numpy.ufuncwhere 关键字参数是 numpy.ndarray 的子类或定义了 numpy.class.__array_ufunc__ 的鸭子类型,它可以使用与输入和输出参数相同的机制来覆盖 ufunc 的行为.请注意,为了正确工作,``where.__array_ufunc__`` 实现将不得不解包 where 参数以将其传递到 ufunc 的默认实现中,或者在调用 super().__array_ufunc__ 之前,对于 numpy.ndarray 子类.

(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 的相同,所以生成的程序将与 NumPy 1.16(从 C-API 的角度来看)兼容.此默认值将在未来的非错误修复版本中增加.您仍然可以针对较旧的 NumPy 版本进行编译并在较新的版本上运行.

更多详情请参见 对于下游包作者.

(gh-23528)

新功能#

np.einsum 现在接受 object 类型的数组#

代码路径将在对象类型数组上调用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 函数返回命名元组#

np.linalg 返回元组的函数现在返回命名元组.这些函数包括 eig(), eigh(), qr(), slogdet(), 和 svd().在某些关键字参数(如 svd(compute_uv=False))下,这些函数返回非元组时,返回类型不变.

(gh-22786)

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

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

(gh-22863)

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

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

(gh-22963)

富士通 C/C++ 编译器现在已支持#

已添加对富士通编译器的支持.要使用富士通编译器进行构建,请运行:

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^{非零} 返回不同的结果.请注意,只有在指数的实部大于零时,该值才有定义.以前,除非虚部严格为零,否则会返回 NaN.返回值要么是 0+0j 要么是 0-0j.

(gh-18535)

新的 DTypePromotionError#

NumPy 现在有一个新的 DTypePromotionError ,当两个 dtypes 不能被提升到一个共同的 dtypes 时使用,例如:

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 参数调用时不保留掩码的问题.#

调用 np.ma.diff 并带有参数 prepend 和/或 append 现在返回一个 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 都是二维时才有效.现在它也适用于非二维数组,就像 np.dot() 一样.

(gh-23322)

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

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 类,并将包含未来的数据类型相关功能.大多数用户不需要直接使用这些类.

(gh-23358)

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

目前,包含带有元数据的dtype表的 *.npy 文件无法被读回.现在,`np.save` 和 np.savez 在保存前会丢弃元数据.

(gh-23371)

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

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

(gh-23652)

有符号和无符号整数总是能正确比较#

uint64int64 在 NumPy 中混合使用时,NumPy 通常会将两者都提升为 float64.这种行为可能会有争议,但对于比较 ==<= 来说很令人困惑,因为返回的结果可能不正确,但由于结果是布尔值,转换是隐藏的.NumPy 现在将通过避免转换为浮点数来返回这些操作的正确结果.

(gh-23713)

性能提升和变化#

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

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

感谢 Intel 公司 对这项工作的赞助.

(gh-23707)

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

对于支持 AVX-512 指令集的处理器,16位和64位 dtypes 的快速排序分别获得了高达15倍和9倍的加速.

感谢 Intel 公司 对这项工作的赞助.

(gh-22315)

__array_function__ 机制现在快得多#

NumPy 中大多数函数的开销现在更小了,尤其是在使用关键字参数时.这一变化显著加快了许多简单函数调用的速度.

(gh-23020)

ufunc.at 可以非常快#

通用 ufunc.at 可以快达9倍.这种加速的条件是:

  • 操作数对齐

  • 无类型转换

如果在满足上述条件的1d参数上使用带有适当索引循环的ufuncs,``ufunc.at`` 可以快达60倍(额外加速7倍).适当的索引循环已添加到 addsubtractmultiplyfloor_dividemaximumminimumfmaxfmin.

内部逻辑类似于常规 ufuncs 使用的逻辑,它们也有快速路径.

感谢 D. E. Shaw 集团 赞助这项工作.

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