NumPy 1.15.0 发行说明#

NumPy 1.15.0 是一个包含大量清理工作、许多旧函数弃用以及改进现有函数的版本。请阅读下面的详细说明,以了解您是否受到影响。

为了测试,我们已将 pytest 作为不再维护的 nose 框架的替代品。旧的基于 nose 的接口仍然保留给可能仍在使用它的下游项目。

此版本支持的 Python 版本为 2.7、3.4-3.7。Wheels 已与 OpenBLAS v0.3.0 链接,这应该可以解决 NumPy 1.14 中报告的一些 linalg 问题。

亮点#

  • NumPy 已切换到 pytest 进行测试。

  • 新的 numpy.printoptions 上下文管理器。

  • 对直方图函数进行了许多改进。

  • 支持 Python 2.7 中的 Unicode 字段名。

  • 改进了对 PyPy 的支持。

  • numpy.einsum 的修复和改进。

新增函数#

  • numpy.gcdnumpy.lcm,用于计算最大公约数和最小公倍数。

  • numpy.ma.stacknumpy.stack 数组连接函数推广到掩码数组。

  • numpy.quantile 函数,一个 percentile 的接口,不带 100 的因子

  • numpy.nanquantile 函数,一个 nanpercentile 的接口,不带 100 的因子

  • numpy.printoptions,一个上下文管理器,它在 `with` 块的作用域内临时设置打印选项

    >>> with np.printoptions(precision=2):
    ...     print(np.array([2.0]) / 3)
    [0.67]
    
  • numpy.histogram_bin_edges,一个无需计算直方图即可获取直方图所用 bin 边缘的函数。

  • 已添加 C 函数 npy_get_floatstatus_barriernpy_clear_floatstatus_barrier 以处理编译器优化改变操作顺序的问题。详情请见下文。

弃用#

  • 内置 pickle 函数的别名已被弃用,建议使用其未别名的 `pickle.<func>` 名称。

    • numpy.loads

    • numpy.core.numeric.load

    • numpy.core.numeric.loads

    • numpy.ma.loads, numpy.ma.dumps

    • numpy.ma.load, numpy.ma.dump - 当使用字符串调用这些函数时,它们在 Python 3 中已失败。

  • 多维索引,除元组以外的类型将被弃用。这意味着 `ind = [slice(None), 0]; arr[ind]` 中的索引列表应更改为元组,例如 `ind = [slice(None), 0]; arr[tuple(ind)]` 或 `arr[(slice(None), 0)]`。此更改对于避免表达式中的歧义是必要的,例如 `arr[[[0, 1], [0, 1]]]`,目前解释为 `arr[array([0, 1]), array([0, 1])]`,未来将解释为 `arr[array([[0, 1], [0, 1]])]`。

  • 来自以下子模块的导入已被弃用,它们将在未来的某个日期被移除。

    • numpy.testing.utils

    • numpy.testing.decorators

    • numpy.testing.nosetester

    • numpy.testing.noseclasses

    • numpy.core.umath_tests

  • 将生成器传递给 numpy.sum 现在已被弃用。这是未记录的行为,但曾有效。以前,它会计算生成器表达式的总和。未来,它可能会返回不同的结果。请使用 `np.sum(np.from_iter(generator))` 或内置的 Python `sum`。

  • C-API 的用户应在释放任何带有 WRITEBACKIFCOPY 标志的数组之前,对其调用 PyArrayResolveWriteBackIfCopyPyArray_DiscardWritebackIfCopy。如果未按需使用这些调用,将发出弃用警告。

  • 使用 `nditer` 的用户,只要迭代器操作数是可写的,就应始终将 nditer 对象用作上下文管理器,以便 numpy 可以管理写回语义,或者应调用 it.close()。否则,在这些情况下可能会发出 RuntimeWarning

  • np.histogram 的 `normed` 参数,在 1.6.0 版本中早已弃用,现在会发出 DeprecationWarning

未来变化#

  • NumPy 1.16 将停止支持 Python 3.4。

  • NumPy 1.17 将停止支持 Python 2.7。

兼容性说明#

编译的测试模块已重命名并设为私有#

以下编译模块已重命名并设为私有

  • umath_tests -> _umath_tests

  • test_rational -> _rational_tests

  • multiarray_tests -> _multiarray_tests

  • struct_ufunc_test -> _struct_ufunc_tests

  • operand_flag_tests -> _operand_flag_tests

umath_tests 模块仍可用于向后兼容,但将来会被移除。

np.savez 返回的 NpzFile 现在是 collections.abc.Mapping#

这意味着它像一个只读字典一样工作,并且有一个新的 `.values()` 方法和 `len()` 实现。

对于 Python 3,这意味着 `.iteritems()` 和 `.iterkeys()` 已被弃用,而 `.keys()` 和 `.items()` 现在返回视图而不是列表。这与 Python 2 和 Python 3 之间内置的 `dict` 类型变化一致。

在某些条件下,`nditer` 必须在上下文管理器中使用#

当使用带有 `"writeonly"` 或 `"readwrite"` 标志的 numpy.nditer 时,在某些情况下 nditer 实际上不会给你一个可写数组的视图。相反,它给你一个副本,如果你对副本进行了更改,nditer 稍后会将这些更改写回你的实际数组。目前,这种写回发生在数组对象被垃圾回收时,这使得该 API 在 CPython 上容易出错,在 PyPy 上则完全损坏。因此,只要 nditer 用于可写数组,它现在就应该用作上下文管理器,例如 `with np.nditer(...) as it: ...`。您也可以显式调用 `it.close()` 来处理上下文管理器不可用的情况,例如在生成器表达式中。

NumPy 已切换到使用 pytest 而不是 nose 进行测试#

最后一个 nose 版本是 2015 年 6 月发布的 1.3.7,该工具的开发已停止,因此 NumPy 现在已切换到使用 pytest。之前一些下游项目使用的旧装饰器和 nose 工具仍然可用,但不会得到维护。标准的测试工具,如 `assert_almost_equal` 等,不受此更改的影响,除了 nose 特定的函数 `import_nose` 和 `raises`。这些函数在 numpy 中不被使用,但为了下游兼容性而被保留。

NumPy 不再使用 `__array_interface__` monkey-patch `ctypes`#

以前 NumPy 会将 `__array_interface__` 属性添加到 `ctypes` 的所有整数类型。

`np.ma.notmasked_contiguous` 和 `np.ma.flatnotmasked_contiguous` 始终返回列表#

这是文档中描述的行为,但以前结果可能是 slice、None 或 list 中的任何一种。

所有下游用户似乎都会检查 `flatnotmasked_contiguous` 的 `None` 结果并将其替换为 `[]`。这些调用者将继续像以前一样工作。

`np.squeeze` 恢复了不能处理 `axis` 参数的对象的旧行为#

在版本 `1.7.0` 之前,numpy.squeeze 没有 `axis` 参数,所有空轴都默认被移除。引入 `axis` 参数后,可以有选择地挤压单个或多个空轴,但旧 API 的预期没有得到尊重,因为仍然可以有选择地从期望移除所有空轴的对象中移除轴(静默成功)。这种对期望旧行为的对象的静默、选择性移除空轴的情况已得到修复,并恢复了旧行为。

非结构化 void 数组的 `.item` 方法现在返回一个 bytes 对象#

`.item` 现在返回一个 `bytes` 对象而不是 buffer 或 byte 数组。这可能会影响假设返回值是可变的旧代码,因为现在它不再是可变的。

`copy.copy` 和 `copy.deepcopy` 不再将 `masked` 转换为数组#

由于 `np.ma.masked` 是一个只读标量,复制应该是一个 no-op。这些函数现在与 `np.copy()` 的行为一致。

结构化数组的多字段索引仍将返回副本#

结构化数组的多字段索引返回视图而非副本的更改已推迟到 1.16。引入了一个新方法 `numpy.lib.recfunctions.repack_fields` 来帮助缓解此更改的影响,该方法可用于编写与 numpy 1.15 和 1.16 都兼容的代码。有关如何更新代码以适应此未来更改的更多信息,请参阅用户指南中“访问多个字段”部分。

C API 更改#

新函数 `npy_get_floatstatus_barrier` 和 `npy_clear_floatstatus_barrier`#

已添加函数 `npy_get_floatstatus_barrier` 和 `npy_clear_floatstatus_barrier`,应取代 `npy_get_floatstatus` 和 `npy_clear_status` 函数。像 GCC 8.1 和 Clang 这样的优化编译器在 ufunc SIMD 函数中使用前一个函数时会重新排列操作顺序,导致在执行我们想要检查其状态的操作之前就检查了 floatstatus 标志。参见 #10339

`PyArray_GetDTypeTransferFunction` 的更改#

`PyArray_GetDTypeTransferFunction` 现在默认使用用户定义的 `copyswapn` / `copyswap` 来处理用户定义的 dtype。如果这导致性能显着下降,请考虑实现 `copyswapn` 来反映 `PyArray_GetStridedCopyFn` 的实现。参见 #10898

新功能#

为整数和对象类型添加了 `np.gcd` 和 `np.lcm` ufuncs#

这些分别计算最大公约数和最小公倍数。它们适用于所有 numpy 整数类型,以及内置的任意精度 `Decimal` 和 `long` 类型。

支持 iOS 的跨平台构建#

构建系统已修改,增加了对 `_PYTHON_HOST_PLATFORM` 环境变量的支持,该变量在从一个平台编译到另一个平台时由 `distutils` 使用。这使得可以为 iOS 目标编译 NumPy。

这只允许您一次为一个特定平台编译 NumPy。创建完整的 iOS 兼容 NumPy 包需要为 iOS 支持的 5 种架构(i386、x86_64、armv7、armv7s 和 arm64)进行构建,并将这 5 个编译后的产品组合成一个单一的“fat”二进制文件。

`np.intersect1d` 添加了 `return_indices` 关键字#

新的关键字 `return_indices` 返回对应于公共元素的两个输入数组的索引。

`np.quantile` 和 `np.nanquantile`#

类似于 `np.percentile` 和 `np.nanpercentile`,但接受 [0, 1] 中的分位数而不是 [0, 100] 中的百分位数。`np.percentile` 现在是一个围绕 `np.quantile` 的薄包装器,额外步骤是除以 100。

构建系统#

为 64 位 RISC-V 架构添加了实验性支持。

改进#

`np.einsum` 更新#

在 `numpy` 和 `opt_einsum` 之间同步 einsum 路径优化技术。特别是,`greedy` 路径由 @jcmgray 进行了许多增强。修复的问题的完整列表如下:

  • 任意内存都可以传递给 `greedy` 路径。修复了 gh-11210。

  • `greedy` 路径已更新,包含更多动态规划思想,避免了大量重复(且昂贵)的调用来确定实际发生的配对收缩。现在处理数百个输入张量需要几秒钟。适用于矩阵乘积状态理论。

  • 重新处理了 gh-11218 和 gh-10352 中发现的广播点错误捕获,使其在过程的早期进行。

  • 增强了 `can_dot` 功能,该功能以前会错过一个边缘情况(gh-11308 的一部分)。

`np.flip` 可以操作多个轴#

`np.flip` 现在在其 `axis` 参数中接受 None 或 int 的元组。如果 axis 为 None,它将翻转所有轴。

`histogram` 和 `histogramdd` 函数已移至 `np.lib.histograms`#

这些最初在 `np.lib.function_base` 中找到。它们仍然可以在其未作用域的 `np.histogram(dd)` 名称下找到,并且为了保持兼容性,已在 `np.lib.function_base.histogram(dd)` 下进行别名。

进行 `from np.lib.function_base import *` 的代码需要更新为新的位置,并且应该考虑将来不要使用 `import *`。

`histogram` 在给出显式 bin 时会接受 NaN 值#

以前,在尝试计算数据的有限范围时它会失败。由于在显式给出 bin 时会忽略范围,因此此错误是不必要的。

请注意,使用 NaN 值调用 `histogram` 会继续引发处理 NaN 值时典型的 `RuntimeWarning`,可以通过 `errstate` 正常抑制。

`histogram` 在给出显式 bin 边缘时,可以处理 datetime 类型#

日期、时间和时间差现在可以进行直方图处理。必须显式提供 bin 边缘,并且尚未自动计算。

`histogram` 的“auto”估计器更好地处理了有限的方差#

IQR 为 0 不再导致 `n_bins=1`,而是在这种情况下选择的 bin 数量与数据大小有关。

`histogram` 和 `histogramdd` 返回的 bin 边缘现在与数据浮点类型匹配#

当传递 `np.float16`、`np.float32` 或 `np.longdouble` 数据时,返回的边缘现在是相同的 dtype。以前,`histogram` 仅在显式给出 bin 时才返回相同的类型,并且 `histogram` 会生成 `float64` bin,而不管输入是什么。

`histogramdd` 允许在子集轴上给出显式范围#

`numpy.histogramdd` 的 `range` 参数现在可以包含 `None` 值,表示相应轴的范围应从数据中计算。以前,这不能按轴指定。

`histogramdd` 和 `histogram2d` 的 `normed` 参数已重命名#

这些参数现在称为 `density`,这与 `histogram` 一致。旧参数仍然有效,但应优先使用新名称。

`np.r_` 可与 0d 数组一起使用,而 `np.ma.mr_` 可与 `np.ma.masked` 一起使用#

传递给 `r_` 和 `mr_` 连接助手的 0d 数组现在被视为长度为 1 的数组。以前,传递这些数组会引发错误。因此,`numpy.ma.mr_` 现在可以正确地处理 `masked` 常量。

`np.ptp` 接受 `keepdims` 参数,以及扩展的轴元组#

`np.ptp`(峰值到峰值)现在可以像 `np.max` 和 `np.min` 一样操作多个轴。

`MaskedArray.astype` 现在与 `ndarray.astype` 相同#

这意味着它接受所有相同的参数,使得更多为 ndarray 编写的代码也能用于掩码数组。

在编译时启用 AVX2/AVX512#

对 simd.inc.src 的更改允许在编译时使用 AVX2 或 AVX512。以前,使用 -march=native 编译 avx2(或 512)仍然会为 SIMD 函数使用 SSE 代码,即使其余代码获得了 AVX2。

`nan_to_num` 在接收标量或 0d 输入时始终返回标量#

以前,对于整数标量输入会返回一个数组,这与浮点输入以及 ufuncs 的行为不一致。对于所有类型的标量或 0d 输入,结果现在都是标量。

`np.flatnonzero` 可处理 numpy 可转换类型#

`np.flatnonzero` 现在使用 `np.ravel(a)` 而不是 `a.ravel()`,因此它适用于列表、元组等。

`np.interp` 返回 numpy 标量而不是内置标量#

以前 `np.interp(0.5, [0, 1], [10, 20])` 会返回一个 `float`,但现在它返回一个 `np.float64` 对象,这更符合其他函数的行为。

此外,`np.interp(object_array_0d, ...)` 的特殊情况不再支持,因为 `np.interp(object_array_nd)` 以前也从未被支持。

由于此更改,`period` 参数现在可以用于 0d 数组。

允许 Python 2 中的 dtype 字段名为 Unicode#

以前 `np.dtype([(u'name', float)])` 在 Python 2 中会引发 `TypeError`,因为字段名只允许使用字节字符串。现在任何 Unicode 字符串字段名都将使用 `ascii` 编解码器进行编码,失败时会引发 `UnicodeEncodeError`。

此更改使得使用 `from __future__ import unicode_literals` 更容易编写 Python 2/3 兼容的代码,而以前这会导致字符串字面量字段名在 Python 2 中引发 TypeError。

比较 ufuncs 接受 `dtype=object`,覆盖默认的 `bool`#

这使得可以逐元素比较具有符号类型的对象数组,这些数组会覆盖 == 和其他运算符以返回表达式,使用 np.equal(a, b, dtype=object)

sort 函数接受 kind='stable'#

到目前为止,要执行稳定排序,用户必须执行

>>> np.sort([5, 2, 6, 2, 1], kind='mergesort')
[1, 2, 2, 5, 6]

因为归并排序是 NumPy 中唯一可用的稳定排序算法。然而,`kind='mergesort'` 并不明确用户想要执行稳定排序,从而损害了可读性。

此更改允许用户指定 `kind='stable'`,从而阐明意图。

就地累积时不要创建临时副本#

当通用函数执行累积时,它们不再创建临时副本,因为输入和输出之间存在重叠。也就是说,下一个要累积的元素在累积结果存储到其位置之前被添加,因此重叠是安全的。避免复制可以提高执行速度。

linalg.matrix_power 现在可以处理矩阵堆栈#

与其他 linalg 中的函数一样,matrix_power 现在可以处理维度大于 2 的数组,这些数组被视为矩阵堆栈。作为更改的一部分,为了进一步提高一致性,第一个参数的名称已从 M 更改为 a,并且非方阵的异常已从 ValueError 更改为 LinAlgError

多维数组的 random.permutation 性能提高#

permutation 对所有输入数组维度都使用了 random.shuffle 的快速路径。以前,快速路径仅用于一维数组。

泛型通用函数现在接受 axesaxiskeepdims 参数#

通过传递 axes 参数(一个包含特定轴索引的元组列表),可以控制泛型通用函数在哪些轴上操作。例如,对于适用于矩阵乘法的签名 (i,j),(j,k)->(i,k),基本元素是二维矩阵,这些矩阵被假定存储在每个参数的最后两个轴上。相应的 `axes` 关键字将是 [(-2, -1), (-2, -1), (-2, -1)]。如果想使用前导维度,则可以传递 [(0, 1), (0, 1), (0, 1)]

为简单起见,对于在一维数组(向量)上操作的泛型通用函数,接受单个整数而不是单元素元组;对于所有输出均为标量的泛型通用函数,可以省略(空)输出元组。因此,对于适用于内积的签名 (i),(i)->(),可以传递 axes=[0, 0] 来指示向量存储在两个输入参数的第一个维度中。

作为泛型通用函数(类似于归约,即作用于单个共享核心维度,例如上面的内积示例)的快捷方式,可以传递 axis 参数。这等效于传递具有相同条目的 axes(例如,对于上面的示例,axes=[(axis,), (axis,)])。

此外,对于归约,对于所有具有相同核心维度数且输出没有核心维度的泛型通用函数,可以传递 keepdims 来在输出中保留大小为 1 的维度,从而允许与原始输入进行正确广播。附加维度的位置可以通过 axes 控制。例如,对于内积示例,keepdims=True, axes=[-2, -2, -2] 将作用于内积示例,keepdims=True, axis=-2 将作用于输入参数的倒数第二个维度,并在输出中保留该位置的大小为 1 的维度。

float128 值现在可以在 ppc 系统上正确打印#

以前,在 ppc 上打印 float128 值存在错误,因为未能考虑这些系统上的特殊双精度浮点格式。float128 现在可以正确四舍五入和唯一地打印。

警告 ppc 用户:如果您使用的 glibc 版本小于等于 2.23,您应该升级它,尤其是在使用 float128 时。在 ppc 上,这些版本的 glibc 的 malloc 经常会错误地对齐分配的内存,这可能导致 numpy 在使用 float128 值时崩溃。

新的 np.take_along_axisnp.put_along_axis 函数#

在多维数组上使用时,argsortargminargmaxargpartition 返回难以用作索引的数组。take_along_axis 提供了一种简单的方法来使用这些索引查找数组中的值,因此

np.take_along_axis(a, np.argsort(a, axis=axis), axis=axis)

与...相同

np.sort(a, axis=axis)

np.put_along_axis 作为写入数组中这些索引的双重操作。