NumPy 1.25.0 发行说明#

NumPy 1.25.0 版本继续致力于改进 dtypes 的处理和提升,提高执行速度以及明确文档. 同时也为未来的 NumPy 2.0.0 版本做准备,从而产生了大量新的和过期的弃用. 亮点包括:

  • 支持 MUSL,现在有 MUSL wheels.

  • 支持 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 替换它的用法. 大多数用户将第二个 scalar_types 参数留给 find_common_type 作为 [] ,在这种情况下, np.result_typenp.promote_types 都更快且更强大. 当不使用 scalar_types 时,主要区别在于替换有意识地将非本地字节顺序转换为本地字节顺序. 此外, find_common_type 返回 object dtype 而不是失败的提升. 当输入不全是数字时,这会导致差异. 重要的是,这也会发生在例如 timedelta/datetime 上,因为 NumPy 提升规则目前有时令人惊讶.

    scalar_types 参数不是 [] 时,事情会变得更加复杂. 在大多数情况下,使用 np.result_type 并传递 Python 值 0 , 0.00j 与在 scalar_types 中使用 int , floatcomplex 具有相同的结果.

    当构建 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 )

  • 现在必须将序列传递到堆叠函数族( stack , vstack , hstack , dstackcolumn_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]) ).

    • 当值从根本上不可比较时(例如,具有不同的数据类型),返回一个全部为 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 shim 已被删除.自从 2019 年以来,从 numpy.testing.utils shim 导入已被弃用,现在该 shim 已被删除.所有导入都应直接从 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 读取多个数组时可能发生的那样,如果 allow_pickle=False ,numpy 之前会引发 ValueError ,如果 allow_pickle=True ,则引发 OSError .现在,在这两种情况下,它都会引发 EOFError .

    ( gh-23105 )

np.pad 使用 mode=wrap 模式填充时,会严格按照原始数据的倍数进行填充#

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

现在,即使填充大小大于原始数组,使用 mode=wrapnp.pad 始终会使用原始数据的严格倍数来填充空间.

( 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 时覆盖 ufunc#

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

有关更多详细信息,请参见 面向下游软件包作者 .

( gh-23528 )

新特性#

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

代码路径将在 object 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 环境变量#

用户现在可以选择在运行时仅启用内置 CPU 功能的子集,方法是指定 NPY_ENABLE_CPU_FEATURES 环境变量.请注意,这些指定的功能必须在基线之外,因为始终假定这些功能存在.如果尝试启用 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 自定义 dtypes 兼容#

现在可以将表示 Unicode 字符串或字节字符串的自定义 dtypes 传递给 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+0j0-0j .

( gh-18535 )

新的 DTypePromotionError#

NumPy 现在有一个新的 DTypePromotionError ,当两个 dtypes 无法提升到通用类型时使用,例如:

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

引发此新异常.

( gh-22707 )

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

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

( gh-22769 )

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

现在使用参数 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 参数#

如果 base 参数可以广播到 startstop 参数,则 numpy.logspacebase 参数现在可以是类数组.

( gh-23275 )

np.ma.dot() 现在支持非二维数组#

以前,只有当 ab 都是二维数组时, np.ma.dot() 才能工作.现在,它也适用于非二维数组,就像 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 类,并将包含未来与 dtype 相关的函数.大多数用户应该不需要直接使用这些类.

( gh-23358 )

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

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

( gh-23371 )

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

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

( gh-23652 )

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

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

( gh-23713 )

性能改进和变更#

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

对于支持 AVX-512 指令集的处理器,用于 np.argsort 的 32 位和 64 位快速排序算法的速度提高了高达 6 倍.

感谢 Intel corporation 赞助这项工作.

( gh-23707 )

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

对于支持 AVX-512 指令集的处理器,16 位和 64 位 dtype 的快速排序速度提高了高达 15 倍和 9 倍.

感谢 Intel corporation 赞助这项工作.

( gh-22315 )

__array_function__ 机制现在快得多#

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

( gh-23020 )

ufunc.at 可以快得多#

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

  • 操作数已对齐

  • 没有类型转换

如果具有适当的索引循环的 ufunc 在具有上述条件的 1d 参数上,则 ufunc.at 可以快达 60 倍(额外的 7 倍加速).已经为 add , subtract , multiply , floor_divide , maximum , minimum , fmaxfmin 添加了适当的索引循环.

内部逻辑类似于用于常规 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 )