NumPy 1.21.0 发行说明#

NumPy 1.21.0 发行版亮点包括

  • 继续 SIMD 工作,涵盖更多函数和平台,

  • 新 dtype 基础设施和类型转换的初步工作,

  • 适用于 Mac 上 Python 3.8 和 Python 3.9 的 universal2 wheel,

  • 改进的文档,

  • 改进的注释,

  • 新的 PCG64DXSM 位生成器用于随机数。

此外,还有大量常规的 bug 修复和其他改进。

此发行版支持的 Python 版本是 3.7-3.9。对 Python 3.10 的官方支持将在其发布时添加。

警告

使用 gcc-11.1 编译 NumPy 1.20.0 存在未解决的问题。

  • 优化级别 -O3 会在运行测试时导致许多不正确的警告。

  • 在某些硬件上,NumPy 会陷入无限循环。

新函数#

添加 PCG64DXSM BitGenerator#

在 NumPy 1.17 首次发布时,PCG64 BitGenerator 在大规模并行环境中的使用已显示出统计学上的弱点,这些弱点在当时并不明显。大多数用户永远不会观察到这个弱点,可以安全地继续使用 PCG64。我们引入了一个新的 PCG64DXSM BitGenerator,它最终将在未来版本中成为 default_rng 使用的新默认 BitGenerator 实现。PCG64DXSM 解决了统计弱点,同时保留了 PCG64 的性能和功能。

有关更多详细信息,请参阅 使用 PCG64DXSM 升级 PCG64

(gh-18906)

已过期弃用#

  • unravel_indexshape 参数不能再作为 dims 关键字参数传递。(在 NumPy 1.16 中已弃用。)

    (gh-17900)

  • 函数 PyUFunc_GenericFunction 已被禁用。它在 NumPy 1.19 中已弃用。用户应直接使用 Python API 调用 ufunc。

    (gh-18697)

  • 函数 PyUFunc_SetUsesArraysAsData 已被禁用。它在 NumPy 1.19 中已弃用。

    (gh-18697)

  • PolyBase 已被移除(在 numpy 1.9.0 中已弃用)。请改用抽象类 ABCPolyBase

    (gh-18963)

  • 未使用的 PolyErrorPolyDomainError 异常已移除。

    (gh-18963)

弃用#

.dtype 属性必须返回一个 dtype#

如果传递给 np.dtype 或作为 dtype=obj 参数的对象其 .dtype 属性不是 dtype,现在会发出 DeprecationWarning。NumPy 将停止尝试递归地强制转换 .dtype 的结果。

(gh-13578)

numpy.convolvenumpy.correlate 的不精确匹配已弃用#

convolvecorrelate 在函数的 mode 参数中发现不区分大小写和/或不精确匹配时,现在会发出警告。请为 mode 参数传递完整的 "same", "valid", "full" 字符串,而不是 "s", "v", "f"

(gh-17492)

np.typeDict 已正式弃用#

np.typeDictnp.sctypeDict 的弃用别名,并且已弃用超过 14 年(6689502)。现在,每当获取 np.typeDict 时,都会发出弃用警告。

(gh-17586)

在创建类似数组的对象时将引发异常#

当对象在访问特殊属性 __array____array_interface__ 期间引发异常时,此异常通常会被忽略。现在,如果异常不是 AttributeError,则会发出警告。要消除警告,引发异常的类型必须调整为引发 AttributeError

(gh-19001)

四个 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_)

(gh-19031)

已过期弃用#

  • numpy.unravel_indexshape 参数不能再作为 dims 关键字参数传递。(在 NumPy 1.16 中已弃用。)

    (gh-17900)

  • 函数 PyUFunc_GenericFunction 已被禁用。它在 NumPy 1.19 中已弃用。用户应直接使用 Python API 调用 ufunc。

    (gh-18697)

  • 函数 PyUFunc_SetUsesArraysAsData 已被禁用。它在 NumPy 1.19 中已弃用。

    (gh-18697)

移除已弃用的 PolyBase 以及未使用的 PolyErrorPolyDomainError#

PolyBase 已被移除(在 numpy 1.9.0 中已弃用)。请改用抽象类 ABCPolyBase

此外,未使用的 PolyErrorPolyDomainError 异常已从 numpy.polynomial 中移除。

(gh-18963)

兼容性说明#

通用函数中的错误类型更改#

通用函数现在在某些情况下对无效输入可能引发不同的错误。主要变化应该是 RuntimeError 被更合适的 TypeError 替换。当同一调用中存在多个错误时,NumPy 现在可能引发不同的错误。

(gh-15271)

__array_ufunc__ 参数验证#

NumPy 现在在调用 __array_ufunc__ 之前会部分验证参数。以前,当已知会发生调度时,可以传递无效参数(例如不存在的关键字参数)。

(gh-15271)

__array_ufunc__ 和额外的位置参数#

以前,所有按位置传递的参数都会检查 __array_ufunc__ 支持。在 reduceaccumulatereduceat 的情况下,所有参数都可以按位置传递。这意味着当它们按位置传递时,以前可能会被要求通过 __array_ufunc__ 处理 ufunc 调用。由于这取决于参数的传递方式(按位置或按关键字),NumPy 现在将仅对输入和输出数组进行调度。例如,NumPy 永远不会在诸如 np.add.reduce 之类的归约中对 where 数组进行调度。

(gh-15271)

验证 Generator.uniform 中的输入值#

np.random.Generator.uniform 中检查 high - low >= 0。如果 low > high,则引发 ValueError。以前,接受并默默交换无序输入,因此如果 low > high,生成的值为 high + (low - high) * random()

(gh-17921)

/usr/include 已从默认包含路径中移除#

使用 numpy.distutils 构建包时的默认包含路径不再包括 /usr/include。此路径通常由编译器添加,并且硬编码它可能会有问题。如果这导致问题,请提出一个 issue。PR 18658 中记录了一个解决方法。

(gh-18658)

dtype=... 比较的变更#

当比较 ufuncs (equal, less 等) 的 dtype= (或 signature) 参数被使用时,这将表示未来所需的输出 dtype。这意味着

np.equal(2, 3, dtype=object)

将给出 FutureWarning,表示它将来会返回一个 object 数组,这目前发生在

np.equal(None, None, dtype=object)

因为 np.array(None) 已经是一个对象数组。(这也适用于其他一些 dtype。)

由于比较通常只返回布尔数组,因此提供任何其他 dtype 将来总是会引发错误,现在则会给出 DeprecationWarning

(gh-18718)

ufuncs 中 dtypesignature 参数的变更#

通用函数参数 dtypesignature (也适用于像 np.add.reduce 这样的归约,它是 np.sum 的实现) 现在在提供的 dtype 不是“基本”dtype 时将发出警告。

NumPy 几乎总是忽略这些输入上的元数据、字节序或时间单位。NumPy 现在将总是忽略它们,如果字节序或时间单位发生变化,则会引发错误。以下是会引发错误的最重要的变更示例。在某些情况下,以前存储的信息没有被忽略,现在所有这些情况都会引发错误

# Previously ignored the byte-order (affect if non-native)
np.add(3, 5, dtype=">i32")

# The biggest impact is for timedelta or datetimes:
arr = np.arange(10, dtype="m8[s]")
# The examples always ignored the time unit "ns":
np.add(arr, arr, dtype="m8[ns]")
np.maximum.reduce(arr, dtype="m8[ns]")

# The following previously did use "ns" (as opposed to `arr.dtype`)
np.add(3, 5, dtype="m8[ns]")  # Now return generic time units
np.maximum(arr, arr, dtype="m8[ns]")  # Now returns "s" (from `arr`)

这同样适用于内部使用这些参数的函数,例如 np.sum。此更改对于在 NumPy 内部实现一致的处理是必需的。

如果遇到这些情况,在大多数情况下,请传递例如 dtype=np.timedelta64,它明确表示一个通用的 timedelta64,不定义任何单位或字节序。如果您需要精确指定输出 dtype,可以通过强制转换输入或使用 out= 提供输出数组来实现。

NumPy 将来可能会选择允许在此处提供确切的输出 dtype,这之前会有一个 FutureWarning

(gh-18718)

Ufunc signature=...dtype= 泛化及 casting#

由于类型提升的改变,np.ufunc(1.0, 1.0, signature=...)np.ufunc(1.0, 1.0, dtype=...) 在 1.21 版本中的行为现在可能与 1.20 版本不同。当以前使用 signature 时,对输入的类型转换检查会放宽,这可能导致不安全地降级输入,尤其是与 casting="unsafe" 结合使用时。

现在保证类型转换是安全的。如果只部分提供了签名,例如使用 signature=("float64", None, None),这可能导致找不到循环(一个错误)。在这种情况下,需要提供完整的签名来强制转换输入。如果使用 dtype="float64" 或只设置输出(例如 signature=(None, None, "float64")),则保持不变。我们预计很少有用户受此更改影响。

此外,dtype="float64" 的含义已被轻微修改,现在严格强制只使用正确的输出(而不是输入)DType。这意味着它现在总是等同于

signature=(None, None, "float64")

(如果 ufunc 有两个输入和一个输出)。由于这在某些情况下可能导致找不到循环,NumPy 通常也会搜索循环

signature=("float64", "float64", "float64")

如果第一次搜索失败。将来,这种行为可能会被定制,以实现更复杂的 ufuncs 的预期结果。(对于某些通用函数,例如 np.ldexp,输入可以有不同的 DType。)

(gh-18880)

Distutils 强制 clang 使用严格浮点模型#

NumPy distutils 现在在使用 clang 编译时将始终添加 -ffp-exception-behavior=strict 编译器标志。Clang 默认为非严格版本,这允许编译器生成无法正确设置浮点警告/错误的代码。

(gh-19049)

C API 变更#

使用 ufunc->type_resolver 和“类型元组”#

NumPy 现在会在调用类型解析器函数之前标准化其“类型元组”参数。请注意,此类型解析器的使用是遗留行为,NumPy 在可能的情况下将不再这样做。强烈不建议调用 ufunc->type_resolverPyUFunc_DefaultTypeResolver,如果这样做,现在将强制使用标准化的类型元组。请注意,这不影响提供类型解析器,预计在大多数情况下它将继续工作。如果您有调用类型解析器的意外用例,请通知 NumPy 开发者,以便找到解决方案。

(gh-18718)

新特性#

添加了一个 mypy 插件,用于处理平台特定的 numpy.number 精度#

现在提供了一个 mypy 插件,用于自动分配某些 number 子类的(平台依赖的)精度,包括 int_intplonglong 等。有关受影响类的全面概述,请参阅 标量类型 文档。

请注意,虽然插件的使用完全是可选的,但如果没有它,上述类的精度将被推断为 Any

要启用该插件,必须将其添加到 mypy 配置文件

[mypy]
plugins = numpy.typing.mypy_plugin

(gh-17843)

让 mypy 插件管理扩展精度的 numpy.number 子类#

mypy 插件(在 numpy/numpy#17843 中引入)已得到扩展:该插件现在会移除在当前平台上不可用的平台特定扩展精度类型的注解。例如,在不可用时它将移除 float128

如果没有该插件,mypy 将认为所有扩展精度类型在所有平台上都可用。

要启用该插件,必须将其添加到 mypy 配置文件

[mypy]
plugins = numpy.typing.mypy_plugin

(gh-18322)

打印浮点值的新 min_digits 参数#

dragon4 浮点打印函数 format_float_positionalformat_float_scientific 中添加了一个新的 min_digits 参数。此关键字参数保证在 unique=True 模式下打印时至少打印给定数量的数字,即使这些额外数字对于唯一指定值来说并非必需。它与设置要打印的最大数字数量的 precision 参数相对应。当在固定精度模式下 unique=False 时,它没有效果,precision 参数固定了数字数量。

(gh-18629)

f2py 现在识别 Fortran 抽象接口块#

f2py 现在可以解析抽象接口块。

(gh-18695)

通过环境变量配置 BLAS 和 LAPACK#

通过使用 NPY_BLAS_LIBSNPY_LAPACK_LIBS 环境变量,可以绕过已安装 BLAS 和 LAPACK 库的自动检测。相反,这些环境变量中的链接标志将直接使用,并且假定语言为 F77。这在自动化构建中特别有用,因为已知安装的 BLAS 和 LAPACK 的确切版本。一个用例是通过存根库链接在运行时替换实际实现。

如果设置了 NPY_CBLAS_LIBS(可选地与 NPY_BLAS_LIBS 一起),也将使用它,通过定义 HAVE_CBLAS 并将环境变量内容附加到链接标志。

(gh-18737)

已为 ndarray 添加了运行时可下标别名#

已添加 numpy.typing.NDArray,它是 np.ndarray[Any, np.dtype[~Scalar]] 的运行时可下标别名。新的类型别名可用于注解具有给定 dtype 和未指定形状的数组。1

1 NumPy 1.21 尚不支持注解数组形状,但预计未来会改变(参见 PEP 646)。

示例#

>>> import numpy as np
>>> import numpy.typing as npt

>>> print(npt.NDArray)
numpy.ndarray[typing.Any, numpy.dtype[~ScalarType]]

>>> print(npt.NDArray[np.float64])
numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

>>> NDArrayInt = npt.NDArray[np.int_]
>>> a: NDArrayInt = np.arange(10)

>>> def func(a: npt.ArrayLike) -> npt.NDArray[Any]:
...     return np.array(a)

(gh-18935)

改进#

numpy.unwrap 的任意 period 选项#

解缠相位区间的尺寸不再仅限于 2 * pi。这对于解缠角度特别有用,也可用于其他区间。

>>> phase_deg = np.mod(np.linspace(0,720,19), 360) - 180
>>> phase_deg
array([-180., -140., -100.,  -60.,  -20.,   20.,   60.,  100.,  140.,
       -180., -140., -100.,  -60.,  -20.,   20.,   60.,  100.,  140.,
       -180.])

>>> unwrap(phase_deg, period=360)
array([-180., -140., -100.,  -60.,  -20.,   20.,   60.,  100.,  140.,
        180.,  220.,  260.,  300.,  340.,  380.,  420.,  460.,  500.,
        540.])

(gh-16987)

np.unique 现在返回单个 NaN#

np.unique 操作一个包含多个 NaN 条目的数组时,其返回值中包含原数组中每个 NaN 条目的 NaN。现在已改进此功能,使得返回的数组只包含一个 NaN 作为最后一个元素。

对于复数数组,所有 NaN 值都被认为是等效的(无论 NaN 是在实部还是虚部)。返回数组的代表选择字典序中最小的一个——关于复数数组的字典序定义,请参见 np.sort

(gh-18070)

Generator.rayleighGenerator.geometric 性能提升#

Generator 中瑞利(Rayleigh)和几何(geometric)随机变量生成的性能已得到改善。这两者都是指数随机变量的转换,并且基于对数的慢逆 CDF 转换已被基于 Ziggurat 的指数变量生成器取代。

当从这些分布中的任一个生成变量时,此更改会中断生成的变量流。

(gh-18666)

占位符注解已得到改进#

所有以前被注解为 typing.Any 的占位符注解都已得到改进。在适当的情况下,它们已被显式函数定义、类或其他杂项对象取代。

(gh-18934)

性能改进#

NumPy 数组的整数除法性能改进#

当除数是常数时,NumPy 数组的整数除法现在使用 libdivide。通过使用 libdivide 和其他一些小的优化,速度有了大幅提升。// 运算符和 np.floor_divide 都利用了这些新变化。

(gh-17727)

提高 np.savenp.load 对小型数组的性能#

np.save 现在对于小型数组来说快得多。

np.load 对于小型数组也更快,但仅限于序列化版本 >= (3, 0) 的情况。

这两项改进都是通过移除仅与 Python 2 相关的检查来实现的,同时仍然保持与可能由 Python 2 创建的数组的兼容性。

(gh-18657)

变更#

numpy.piecewise 输出类现在与输入类匹配#

ndarray 子类作为输入用于 piecewise 时,它们会被传递给函数。输出也将是相同的子类。

(gh-18110)

启用 Accelerate Framework#

随着 macOS 11.3 的发布,NumPy 在使用 Accelerate Framework 实现的 BLAS 和 LAPACK 时遇到的几个不同问题应该已经解决。此更改在 macOS 上启用了 Accelerate Framework 选项。如果发现其他问题,请使用开发者反馈助手工具 (https://developer.apple.com/bug-reporting/) 向 Accelerate 提交错误报告。我们打算及时解决问题,并计划继续支持和更新我们的 BLAS 和 LAPACK 库。

(gh-18874)