NumPy 1.17.0 发行说明#

此 NumPy 版本包含许多新功能,这些功能应大大提高其性能和实用性,请参阅下面的"亮点"部分以获取摘要.支持的 Python 版本是 3.5-3.7,请注意 Python 2.7 已被删除. Python 3.8b2 应该可以使用已发布的源程序包,但是没有未来保证.

下游开发人员应使用 Cython >= 0.29.11 以获得 Python 3.8 支持,并使用 OpenBLAS >= 3.7(目前尚未发布)以避免 Skylake 架构上的问题. PyPI 上的 NumPy wheels 由 OpenBLAS 开发分支构建,以避免这些问题.

亮点#

  • 添加了一个新的可扩展 random 模块,以及四个可选的 random number generators 和改进的种子设定,专为并行进程而设计.当前可用的位生成器是 MT19937 , PCG64 , PhiloxSFC64 .请参见下面的"新功能".

  • NumPy 的 FFT 实现已从 fftpack 更改为 pocketfft,从而带来更快,更准确的变换以及对素数长度数据集的更好处理.请参见下面的"改进".

  • 新的基数排序和 timsort 排序方法.目前无法选择将使用哪种方法.它们被硬连接到数据类型,并在将 stablemergesort 作为方法传递时使用.请参见下面的"改进".

  • 现在默认可以覆盖 numpy 函数,请参阅下面的 __array_function__ .

新函数#

弃用#

当传递 float 代替 int 时, numpy.polynomial 函数会发出警告#

以前,此模块中的函数会接受 float 值,只要它们是整数( 1.0 , 2.0 等).为了与 numpy 的其余部分保持一致,现在不建议这样做,并且将来会引发 TypeError .

同样,传递像 0.5 这样的浮点数来代替整数现在将引发 TypeError 而不是先前的 ValueError .

弃用 numpy.distutils.exec_commandtemp_file_name#

这些函数的内部使用已重构,并且有更好的替代方法. 将 exec_command 替换为 subprocess.Popen ,并将 temp_file_name 替换为 tempfile.mkstemp .

C-API 包装数组的可写标志#

当从 C-API 创建数组以包装指向数据的指针时,我们拥有的关于数据的读写性质的唯一指示是在创建期间设置的 writeable 标志. 强制将标志设置为可写入是危险的. 将来,将无法从 python 将 writeable 标志切换为 True . 此弃用不应影响很多用户,因为以这种方式创建的数组在实践中非常罕见,并且只能通过 NumPy C-API 获得.

numpy.nonzero 不应再在 0d 数组上调用#

numpy.nonzero 在 0d 数组上的行为令人惊讶,使其使用几乎总是错误的. 如果打算使用旧的行为,则可以通过使用 nonzero(atleast_1d(arr)) 而不是 nonzero(arr) 来保留该行为,而不会发出警告. 在将来的版本中,很可能会引发 ValueError .

写入 numpy.broadcast_arrays 的结果将发出警告#

通常, numpy.broadcast_arrays 返回一个具有内部重叠的可写数组,因此写入该数组是不安全的. 将来的版本会将 writeable 标志设置为 False ,并要求用户在确定要这样做的情况下手动将其设置为 True . 现在,写入它将发出弃用警告,并带有将 writeable 标志设置为 True 的说明. 请注意,如果在设置该标志之前对其进行检查,则会发现该标志已经为 True . 但是,显式设置它(就像在将来的版本中需要做的那样)会清除用于产生弃用警告的内部标志. 为了帮助缓解混乱,当访问 writeable 标志状态时,将发出一条额外的 FutureWarning 来阐明矛盾.

请注意,对于 C 端缓冲协议,除非请求可写缓冲,否则此类数组将立即返回只读缓冲.如果请求可写缓冲,将发出警告.当使用 Cython 时,应将 const 限定符与此类数组一起使用,以避免警告(例如 cdef const double[::1] view ).

未来变化#

dtypes 中的 Shape-1 字段在未来版本中不会折叠为标量#

目前,指定为 [(name, dtype, 1)]"1type" 的字段被解释为标量字段(即,与 [(name, dtype)][(name, dtype, ()] 相同).现在会引发 FutureWarning;在未来版本中,它将被解释为 shape-(1,) 字段,即与 [(name, dtype, (1,))]"(1,)type" 相同(与 [(name, dtype, n)] / "ntype"n>1 一致, 这已与 [(name, dtype, (n,)] / "(n,)type" 等效).

兼容性说明#

float16 次正规数舍入#

从不同的浮点精度转换为 float16 在某些边缘情况下使用了不正确的舍入.这意味着在极少数情况下,次正规数结果现在将被向上舍入而不是向下舍入,从而更改结果的最后一位 (ULP).

使用 divmod 时出现带符号零#

1.12.0 版本开始,当结果为零时,numpy 在使用 divmodfloor_divide 函数时错误地返回了负号零.例如:

>>> np.zeros(10)//1
array([-0., -0., -0., -0., -0., -0., -0., -0., -0., -0.])

在此版本中,结果已正确返回为正号零:

>>> np.zeros(10)//1
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

MaskedArray.mask 现在返回掩码的视图,而不是掩码本身#

返回掩码本身是不安全的,因为它可以在适当的位置进行重塑,这将违反掩码数组代码的期望. mask 的行为现在与 data 一致,后者也返回一个视图.

如果需要,仍然可以使用 ._mask 访问底层掩码.包含 assert x.mask is not y.mask 或类似内容的测试需要更新.

不要在 numpy.frombuffer 中查找 __buffer__ 属性#

numpy.frombuffer 中查找 __buffer__ 属性是未记录且无效的.此代码已删除.如果需要,请改用 frombuffer(memoryview(obj), ...) .

outtake , choose , put 中针对内存重叠进行缓冲#

如果提供了这些函数的 out 参数并且与其他参数存在内存重叠,则现在对其进行缓冲以避免依赖于顺序的行为.

加载时 Unpickling 需要显式选择加入#

函数 loadlib.format.read_array 采用一个 allow_pickle 关键字,该关键字现在默认为 False ,以响应 CVE-2019-6446 .

旧随机模块中随机流的潜在变化#

由于在将 log 应用于随机浮点数时存在错误,因此如果基础 MT19937 随机流中生成 0 ,则从 beta , binomial , laplace , logistic , logseriesmultinomial 采样时,流可能会发生变化. 有 \(10^{53}\) 分之 1 的可能性会发生这种情况,因此对于任何给定的种子,流发生变化的概率极小.如果在底层生成器中遇到 0 ,则现在将丢弃生成的不正确的值( numpy.infnumpy.nan ).

i0 现在总是返回与输入形状相同的结果#

以前,输出被压缩了,例如,仅具有单个元素的输入将导致返回数组标量,并且具有诸如 (10, 1) 之类的形状的输入将产生不会针对输入进行广播的结果.

请注意,我们通常建议使用 SciPy 实现而不是 numpy 实现:它是一个用 C 编写的合适的 ufunc,并且速度快了一个数量级以上.

can_cast 不再假定允许所有不安全的强制转换#

以前, can_cast 对于几乎所有 casting='unsafe' 的输入都返回 True ,即使对于无法进行强制转换的情况,例如从结构化 dtype 到常规 dtype.这已得到修复,使其与实际使用(例如, .astype 方法)进行强制转换更加一致.

ndarray.flags.writeable 可以稍微更频繁地切换为 true#

在极少数情况下,尽管基本数组是可写的,但无法将数组从不可写切换为可写.如果中间 ndarray.base 对象是可写的,则会发生这种情况.以前,只有最深的基本对象才被考虑用于此决策.但是,在极少数情况下,此对象没有必要的信息.在这种情况下,永远不允许切换到可写.现在已经修复了.

C API 变更#

维度或步长输入参数现在通过 npy_intp const* 传递#

以前这些函数参数被声明为更严格的 npy_intp* ,这阻止了调用者传递常量数据.此更改是向后兼容的,但现在允许像这样的代码:

npy_intp const fixed_dims[] = {1, 2, 3};
// no longer complains that the const-qualifier is discarded
npy_intp size = PyArray_MultiplyList(fixed_dims, 3);

新特性#

新的可扩展 numpy.random 模块,带有可选择的随机数生成器#

添加了一个新的可扩展 numpy.random 模块,以及四个可选择的随机数生成器和改进的为并行进程设计的种子.当前可用的 Bit GeneratorsMT19937 , PCG64 , PhiloxSFC64 . PCG64 是新的默认设置,而 MT19937 为了向后兼容而保留.请注意,遗留的 random 模块未更改且现在已冻结,您当前的结果不会更改.更多信息请参见 API change descriptiontop-level view 文档.

libFLAME#

支持使用 libFLAME 线性代数包作为 LAPACK 实现来构建 NumPy,详情请参见 libFLAME .

用户定义的 BLAS 检测顺序#

distutils 现在使用一个环境变量(逗号分隔且不区分大小写)来确定 BLAS 库的检测顺序.默认情况下 NPY_BLAS_ORDER=mkl,blis,openblas,atlas,accelerate,blas .但是,要强制使用 OpenBLAS,只需执行以下操作:

NPY_BLAS_ORDER=openblas python setup.py build

这会强制使用 OpenBLAS.对于安装了 MKL 但希望尝试不同实现的用户,这可能会有所帮助.

用户定义的 LAPACK 检测顺序#

numpy.distutils 现在使用一个环境变量(逗号分隔且不区分大小写)来确定 LAPACK 库的检测顺序.默认情况下 NPY_LAPACK_ORDER=mkl,openblas,flame,atlas,accelerate,lapack .但是,要强制使用 OpenBLAS,只需执行以下操作:

NPY_LAPACK_ORDER=openblas python setup.py build

这会强制使用 OpenBLAS.对于安装了 MKL 但希望尝试不同实现的用户,这可能会有所帮助.

Timsort 和基数排序已取代归并排序以实现稳定排序#

基数排序和 timsort 都已实现,现在用于代替归并排序.由于需要保持向后兼容性,排序 kind 选项 "stable""mergesort" 已经彼此别名,实际的排序实现取决于数组类型.基数排序用于 16 位或更小的小整数类型,而 timsort 用于其余类型.Timsort 在包含已排序或接近排序的数据的数据上具有改进的性能,并且在随机数据上执行类似归并排序的操作,并且需要 \(O(n/2)\) 的工作空间.timsort 算法的详细信息可以在 CPython listsort.txt 中找到.

packbitsunpackbits 接受一个 order 关键字#

order 关键字默认为 big ,并将相应地对位进行排序.对于 'order=big' ,3 将变为 [0, 0, 0, 0, 0, 0, 1, 1] ,对于 order=little ,则变为 [1, 1, 0, 0, 0, 0, 0, 0]

unpackbits 现在接受一个 count 参数#

count 允许预先子集化要解包的位数,而不是稍后重塑和子集化,从而使 packbits 操作可逆,并且解包的浪费更少.大于可用位数的计数会添加零填充.负计数会从末尾而不是从开头修剪位.None 计数实现了解包所有内容的现有行为.

linalg.svdlinalg.pinv 在厄米输入上可以更快#

这些函数现在接受一个 hermitian 参数,与 1.14.0 中添加到 linalg.matrix_rank 的参数匹配.

现在支持对两个 timedelta64 操作数执行 divmod 运算#

divmod 运算符现在处理两个 timedelta64 操作数,类型签名为 mm->qm .

fromfile 现在接受一个 offset 参数#

此函数现在接受一个 offset 关键字参数,用于二进制文件,它指定从文件当前位置的偏移量(以字节为单位).默认为 0 .

pad 的新模式 “empty”]#

此模式将数组填充到所需的形状,而不初始化新条目.

浮点标量实现 as_integer_ratio 以匹配内置 float#

这返回一个 (numerator, denominator) 对,可用于构造 fractions.Fraction .

结构化的 dtype 对象可以用多个字段名进行索引#

arr.dtype[['a', 'b']] 现在返回一个等效于 arr[['a', 'b']].dtype 的 dtype,以便与 arr.dtype['a'] == arr['a'].dtype 保持一致.

与使用字段列表索引的结构化数组的 dtype 相似,此 dtype 具有与原始数组相同的 itemsize ,但仅保留字段的子集.

这意味着 arr[['a', 'b']]arr.view(arr.dtype[['a', 'b']]) 是等效的.

.npy 文件支持 unicode 字段名称#

引入了新的 3.0 格式版本,它支持具有非 latin1 字段名称的结构化类型. 在需要时自动使用.

改进#

数组比较断言包含最大差异#

数组比较测试(如 testing.assert_allclose )中的错误消息现在包括"最大绝对差"和"最大相对差",以及之前的"不匹配"百分比. 此信息使更新绝对和相对误差容限变得更加容易.

使用 pocketfft 库替换基于 fftpack 的 fft 模块#

两种实现都具有相同的祖先( Paul N. Swarztrauber 的 Fortran77 FFTPACK),但是 pocketfft 包含其他修改,这些修改在某些情况下既提高了准确性又提高了性能. 对于包含大质因子的 FFT 长度,pocketfft 使用 Bluestein 算法,该算法保持 \(O(N log N)\) 运行时间复杂度,而不是对于质数长度恶化为 \(O(N*N)\) . 此外,具有近似质数的实值 FFT 的准确性得到了提高,并且与复数值 FFT 相当.

numpy.ctypeslib 中对 ctypes 支持的进一步改进#

添加了一个新的 numpy.ctypeslib.as_ctypes_type 函数,可用于将 dtype 转换为最佳猜测 ctypes 类型. 感谢此新功能, numpy.ctypeslib.as_ctypes 现在支持更广泛的数组类型,包括结构,布尔值和非本机字节序的整数.

numpy.errstate 现在也是一个函数装饰器#

目前,如果您有一个像这样的函数:

def foo():
    pass

并且您想将整个内容包装在 errstate 中,则必须像这样重写它:

def foo():
    with np.errstate(...):
        pass

但是通过此更改,您可以执行以下操作:

@np.errstate(...)
def foo():
    pass

从而节省了一个缩进级别

numpy.expnumpy.log 加速了 float32 实现#

explog 的 float32 实现在运行时检测到的 AVX2/AVX512 指令集现在受益. exp 的最大 ulp 误差为 2.52, log 的最大 ulp 误差为 3.83.

提高 numpy.pad 的性能#

通过使用所需的填充形状的预分配数组填充而不是使用连接,该函数的性能在大多数情况下得到了改善.

numpy.interp 更可靠地处理无穷大#

在某些情况下, interp 以前会返回 nan ,现在它返回适当的无穷大.

Pathlib 支持 fromfile , tofilendarray.dump#

fromfile , ndarray.ndarray.tofilendarray.dump 现在支持 file / fid 参数的 pathlib.Path 类型.

针对 bool 和 int 类型的专用 isnan , isinfisfinite ufuncs#

布尔和整数类型无法存储 naninf 值,这使我们可以提供比以前的方法快 250 倍的专用 ufuncs.

isfinite 支持 datetime64timedelta64 类型#

以前, isfinite 过去常常在使用这两种类型时引发 TypeError .

新关键字已添加到 nan_to_num#

nan_to_num 现在接受关键字 nan , posinfneginf ,允许用户定义分别替换 nan ,正负 np.inf 值的 value.

由分配的过大数组引起的 MemoryError 更加具有描述性#

通常,MemoryError 的原因是错误的广播,这会导致非常大且不正确的形状. 错误消息现在包含此形状,以帮助诊断失败的原因.

floor , ceiltrunc 现在尊重内置的魔术方法#

现在,当对对象数组调用这些 ufunc 时,它们会调用 __floor__ , __ceil____trunc__ 方法,从而使它们与 decimal.Decimalfractions.Fraction 对象兼容.

quantile 现在适用于 fraction.Fractiondecimal.Decimal 对象#

通常,这可以更优雅地处理对象数组,并且如果使用精确的算术类型,则可以避免浮点运算.

matmul 中对对象数组的支持#

现在可以将 matmul (或 @ 运算符)与对象数组一起使用. 例如,现在可以执行以下操作:

from fractions import Fraction
a = np.array([[Fraction(1, 2), Fraction(1, 3)], [Fraction(1, 3), Fraction(1, 2)]])
b = a @ a

变更#

medianpercentile 系列函数不再警告 nan#

numpy.median , numpy.percentilenumpy.quantile 过去在遇到 nan 时会发出 RuntimeWarning . 由于它们返回 nan 值,因此该警告是多余的,已被删除.

timedelta64 % 0 的行为已调整为返回 NaT#

两个 np.timedelta64 操作数的模运算,当除数为零时,现在返回 NaT ,而不是返回零.

NumPy 函数现在始终支持使用 __array_function__ 进行覆盖#

NumPy 现在始终检查 __array_function__ 方法,以实现对非 NumPy 数组上的 NumPy 函数的覆盖,如 NEP 18 中所述. 如果设置了适当的环境变量,则该功能已可在 NumPy 1.16 中进行测试,但现在始终启用.

lib.recfunctions.structured_to_unstructured 不会压缩单字段视图#

以前, structured_to_unstructured(arr[['a']]) 会产生一个与 structured_to_unstructured(arr[['a', b']]) 不一致的挤压结果.这是偶然的.可以使用 structured_to_unstructured(arr[['a']]).squeeze(axis=-1) 或更简单地使用 arr['a'] 来保留旧的行为.

clip 现在在底层使用 ufunc#

这意味着通过 descr->f->fastclip 在 C 中为自定义 dtype 注册 clip 函数已被弃用 - 它们应该使用 ufunc 注册机制,附加到 np.core.umath.clip ufunc.

这也意味着 clip 接受 wherecasting 参数,并且可以用 __array_ufunc__ 覆盖.

此更改的一个结果是,旧的 clip 的某些行为已被弃用:

  • nan 传递给表示"不剪裁"作为其中一个或两个边界. 这在所有情况下都无效,并且可以通过传递适当符号的无穷大来更好地处理.

  • 当传递 out 参数时,默认情况下使用"不安全"转换. 显式使用 casting="unsafe" 将消除此警告.

此外,还有一些边界情况的行为变更:

  • 填充 max < min 已更改为在不同的 dtype 之间更加一致,但不应依赖.

  • 标量 minmax 参与提升规则,就像它们在所有其他 ufunc 中一样.

__array_interface__ offset 现在按照文档工作#

该接口可能使用了一个被错误忽略的 offset 值.

savez 中的 Pickle 协议设置为 3 以用于 force zip64 标志#

savez 没有使用 force_zip64 标志,这会将归档文件的大小限制为 2GB. 但是使用该标志需要我们使用 pickle 协议 3 来写入 object 数组. 使用的协议已提升到 3,这意味着该归档文件将无法被 Python2 读取.

使用不存在的字段索引的结构化数组会引发 KeyError 而不是 ValueError#

结构化类型的 arr['bad_field'] 会引发 KeyError ,以与 dict['bad_field'] 保持一致.