NumPy 1.12.0 发行说明#
此版本支持 Python 2.7 和 3.4 - 3.6。
亮点#
NumPy 1.12.0 版本包含大量修复和改进,但其中只有少数特别突出。因此,挑选亮点有些随意,但以下内容可能特别值得关注或预示未来可能产生影响的领域。
np.einsum
中的操作顺序现在可以进行优化,以大幅提升速度。np.vectorize
新增signature
参数,用于核心维度向量化。许多函数中添加了
keepdims
参数。用于测试警告的新上下文管理器
numpy.distutils
中支持 BLIS对 PyPy 的支持大大改进(尚未完成)
停止支持#
已停止支持 Python 2.6、3.2 和 3.3。
新增支持#
已添加对 PyPy 2.7 v5.6.0 的支持。虽然尚未完全完成(
nditer updateifcopy
尚不支持),但这标志着 PyPy C-API 兼容层的一个里程碑。
构建系统更改#
库顺序得以保留,而不是重新排序以匹配目录的顺序。
弃用#
ndarray 对象 data
属性的赋值#
如 gh-7083 中指出,赋值 'data' 属性本质上是不安全的操作。此功能将在未来移除。
linspace
中 num 属性的不安全整数转换#
当 num 无法安全地解释为整数时,np.linspace
现在会引发 DeprecationWarning。
binary_repr
的位宽参数不足#
如果传递给 binary_repr
的 'width' 参数不足以表示该数字的二进制(正数)或二进制补码(负数)形式,该函数过去会默默地忽略该参数,并返回使用所需最少位数表示的形式。从用户角度来看,这种行为现在被认为是不安全的,未来将引发错误。
未来更改#
在 1.13 版本中,NAT 总是比较为 False,除了
NAT != NAT
会为 True。简而言之,NAT 的行为将类似于 NaN。在 1.13 版本中,
np.average
将保留子类,以匹配大多数其他 NumPy 函数(如np.mean
)的行为。特别是,这意味着返回标量的调用可能会返回一个 0 维子类对象。
结构化数组的多字段操作#
在 1.13 版本中,涉及多个字段的结构化数组的行为将以两种方式改变:
首先,在 1.13 版本中,使用多个字段(例如 arr[['f1', 'f3']]
)对结构化数组进行索引将返回原始数组的视图,而不是副本。请注意,返回的视图将包含与原始数组中插入字段对应的额外填充字节,这与 1.12 版本中的副本不同,这将影响诸如 arr[['f1', 'f3']].view(newdtype)
的代码。
其次,对于 NumPy 1.6 到 1.12 版本,结构化数组之间的赋值是“按字段名”进行的:目标数组中的字段被设置为源数组中同名字段的值,如果源数组没有该字段则设置为 0。
>>> a = np.array([(1,2),(3,4)], dtype=[('x', 'i4'), ('y', 'i4')])
>>> b = np.ones(2, dtype=[('z', 'i4'), ('y', 'i4'), ('x', 'i4')])
>>> b[:] = a
>>> b
array([(0, 2, 1), (0, 4, 3)],
dtype=[('z', '<i4'), ('y', '<i4'), ('x', '<i4')])
在 1.13 版本中,赋值将改为“按位置”进行:目标数组的第 N 个字段将设置为源数组的第 N 个字段,而不考虑字段名。旧的行为可以通过在赋值前使用索引重新排序字段来获得,例如 b[['x', 'y']] = a[['y', 'x']]
。
兼容性说明#
DeprecationWarning 变为错误#
使用浮点数索引会引发
IndexError
,例如 a[0, 0.0]。使用非整数 array_like 索引会引发
IndexError
,例如a['1', '2']
。使用多个省略号索引会引发
IndexError
,例如a[..., ...]
。非整数用作索引值会引发
TypeError
,例如在reshape
、take
中,以及指定缩减轴时。
FutureWarning 变为行为改变#
如果未给定 dtype,
np.full
现在返回填充值的 dtype 数组,而不是默认为浮点数。如果参数是 ndarray 的子类,
np.average
将发出警告,因为从 1.13 版本开始将保留子类。(参见未来更改)
power
和 **
对整数到负整数幂次引发错误#
以前的行为取决于是否涉及 NumPy 标量整数或 NumPy 整数数组。
对于数组
零的负整数幂返回最小整数值。
1 和 -1 的负整数幂均返回正确值。
其余整数在计算负整数幂时返回零。
对于标量
零的负整数幂返回最小整数值。
1 和 -1 的负整数幂均返回正确值。
其余整数有时返回零,有时返回正确的浮点数,这取决于整数类型组合。
所有这些情况现在都将引发 ValueError
,除了那些共同类型为浮点数(例如 uint64 和 int8)的整数组合。我们认为,制定一个简单的规则是最好的方法,而不是为整数单位设置特殊例外。如果需要负幂,请使用非精确类型。
默认启用宽松步幅检查#
这将对那些假定 F_CONTIGUOUS
和 C_CONTIGUOUS
互斥并可用于确定现在同时满足两者条件的数组的默认顺序的代码产生一些影响。
np.percentile
的‘中点’插值方法对精确索引进行了修复#
当‘lower’和‘higher’方法一致时,‘midpoint’插值器现在会给出相同的结果。之前‘lower’ + 0.5 的行为已修复。
keepdims
关键字参数传递给用户类方法#
接受 keepdims
关键字参数的 NumPy 函数现在会将该值传递给 ndarray 子类上的相应方法。以前,keepdims
关键字会被静默丢弃。这些函数现在具有以下行为:
如果用户未提供
keepdims
,则不会向底层方法传递任何关键字。任何用户提供的
keepdims
值都将作为关键字参数传递给该方法。
如果方法不支持 keepdims
关键字参数且用户显式传入 keepdims
,则会引发错误。
以下函数已更改:sum
, product
, sometrue
, alltrue
, any
, all
, amax
, amin
, prod
, mean
, std
, var
, nanmin
, nanmax
, nansum
, nanprod
, nanmean
, nanmedian
, nanvar
, nanstd
bitwise_and
恒等式已更改#
之前的恒等式是 1,现在是 -1。更多解释请参见“改进”部分。
ma.median
在遇到未掩码的无效值时发出警告并返回 NaN#
与未掩码中位数类似,掩码中位数 ma.median 现在在存在未掩码 NaN 的切片中会发出 Runtime 警告并返回 NaN。
assert_almost_equal
的更高一致性#
标量的精度检查已更改为与数组的精度检查相匹配。现在是
abs(actual - desired) < 1.5 * 10**(-decimal)
请注意,这比之前文档中描述的更宽松,但与 assert_array_almost_equal
中使用的先前实现一致。由于实现的更改,一些之前未失败的非常精细的测试可能会失败。
测试期间 NoseTester
警告行为#
当给出 raise_warnings="develop"
时,所有未捕获的警告现在都将被视为测试失败。以前只有选定的警告会被引发。未被捕获或引发的警告(主要在发布模式下)将在测试周期中显示一次,类似于默认的 Python 设置。
assert_warns
和 deprecated
装饰器更具体#
The assert_warns
函数和上下文管理器现在对给定的警告类别更具体。这种增强的特异性使得它们根据外部警告设置进行处理。这意味着在上下文中给出错误类别警告并被忽略的情况下,可能不会引发警告。另外,增强的特异性可能意味着之前被错误忽略的警告现在将显示或引发。另请参阅新的 suppress_warnings
上下文管理器。deprecated
装饰器也同样如此。
C API#
无变化。
新特性#
as_strided
的 writeable 关键字参数#
np.lib.stride_tricks.as_strided
现在有一个 writeable
关键字参数。当不期望对返回的数组进行写入操作时,可以将其设置为 False,以避免意外的不可预测写入。
rot90
的 axes
关键字参数#
rot90
中的 axes
关键字参数决定了数组旋转的平面。它默认为 axes=(0,1)
,与原始函数一致。
泛化的 flip
#
flipud
和 fliplr
分别沿 axis=0 和 axis=1 反转数组的元素。新添加的 flip
函数沿任何给定轴反转数组的元素。
np.count_nonzero
现在有一个axis
参数,允许在扁平化数组对象之外的更多维度上生成非零计数。
numpy.distutils
中支持 BLIS#
现在支持针对 BLIS 库提供的 BLAS 实现进行构建。请参阅 [blis]
部分在 site.cfg.example
中(在 NumPy 仓库或源代码分发的根目录中)。
numpy/__init__.py
中的钩子,用于运行特定于分发的检查#
NumPy 的二进制分发可能需要在 NumPy 初始化期间运行特定的硬件检查或加载特定的库。例如,如果我们将 NumPy 与需要 SSE2 指令的 BLAS 库一起分发,我们希望检查运行 NumPy 的机器是否支持 SSE2,以便提供有用的错误信息。
在 numpy/__init__.py
中添加一个钩子,用于导入一个 numpy/_distributor_init.py
文件,该文件在标准 NumPy 源代码中将保持为空(除了一个文档字符串),但可以被制作 NumPy 二进制分发的人覆盖。
新增 nan 函数 nancumsum
和 nancumprod
#
已添加 nan 函数 nancumsum
和 nancumprod
,用于通过忽略 NaN 来计算 cumsum
和 cumprod
。
np.interp
现在可以插值复数值#
np.lib.interp(x, xp, fp)
现在允许被插值数组 fp
为复数,并将在 complex128
精度下进行插值。
新增多项式求值函数 polyvalfromroots
#
新函数 polyvalfromroots
根据多项式的根在给定点求值多项式。这对于高阶多项式很有用,因为在机器精度下,展开成多项式系数会不准确。
新增数组创建函数 geomspace
#
新函数 geomspace
生成一个几何序列。它类似于 logspace
,但直接指定了 start 和 stop:geomspace(start, stop)
的行为与 logspace(log10(start), log10(stop))
相同。
用于测试警告的新上下文管理器#
测试工具中新增了一个上下文管理器 suppress_warnings
。此上下文管理器旨在帮助可靠地测试警告。特别是可靠地过滤/忽略警告。在 Python 3.4.x 之前的版本中使用“ignore”过滤器忽略警告,可能会导致这些(或类似)警告无法可靠地测试。
该上下文管理器允许过滤(以及记录)警告,类似于 catch_warnings
上下文,但允许更简单的特异性。此外,打印未过滤的警告或嵌套上下文管理器将按预期工作。另外,可以将上下文管理器用作装饰器,当多个测试需要隐藏相同的警告时,这会很有用。
新增掩码数组函数 ma.convolve
和 ma.correlate
#
这些函数包装了非掩码版本,但会通过掩码值进行传播。有两种不同的传播模式。默认模式会导致掩码值通过掩码污染结果,而另一种模式仅在没有替代方案时才输出掩码。
新增 float_power
通用函数#
新的 float_power
通用函数类似于 power
函数,但所有计算都以至少 float64 的精度进行。NumPy 邮件列表中曾就如何处理整数的负整数幂进行了长时间讨论,其中一个受欢迎的提议是 __pow__
运算符应始终返回至少 float64 精度的结果。float_power
函数实现了该选项。请注意,它不支持对象数组。
np.loadtxt
现在支持将单个整数作为 usecol
参数#
现在允许使用 usecol=n
来读取文件的第 n 列,而不是使用 usecol=(n,)
。此外,当将非整数作为列索引传递时,错误消息也更加用户友好。
改进了 histogram
的自动分箱估计器#
通过 bins
参数向 histogram
添加了 'doane' 和 'sqrt' 估计器。新增了对具有自动分箱估计的范围受限直方图的支持。
np.roll
现在可以同时滚动多个轴#
roll
的 shift
和 axis
参数现在相互广播,并且每个指定的轴都会相应地移动。
已为 ndarray 实现 __complex__
方法#
现在,对大小为 1 的数组调用 complex()
将转换为 Python 复数。
现在支持 pathlib.Path
对象#
标准的 np.load
、np.save
、np.loadtxt
、np.savez
等函数现在可以接受 pathlib.Path
对象作为参数,而不是文件名或已打开的文件对象。
np.finfo
的新增 bits
属性#
这使得 np.finfo
与已经拥有该属性的 np.iinfo
保持一致。
np.vectorize
的新增 signature
参数#
该参数允许以 NumPy 泛化通用函数的风格对具有核心维度的用户定义函数进行向量化。这使得可以对更广泛的函数类别进行向量化。例如,一个将两个向量组合生成标量的任意距离度量可以通过 signature='(n),(n)->()'
进行向量化。有关完整详细信息,请参阅 np.vectorize
。
对整数数组的除法发出 py3kwarnings 警告#
为了帮助人们将代码库从 Python 2 迁移到 Python 3,Python 解释器有一个方便的选项 -3,它会在运行时发出警告。其中一个警告是关于整数除法。
$ python -3 -c "2/3"
-c:1: DeprecationWarning: classic int division
在 Python 3 中,新的整数除法语义也适用于 NumPy 数组。此版本中,NumPy 将发出类似的警告。
$ python -3 -c "import numpy as np; np.array(2)/np.array(3)"
-c:1: DeprecationWarning: numpy: classic int division
numpy.sctypes
现在也在 Python3 中包含 bytes#
以前,它在 Python2 中包含 str (bytes) 和 unicode,但在 Python3 中只包含 str (unicode)。
改进#
bitwise_and
恒等式已更改#
之前的恒等式是 1,结果是当使用 reduce 方法时,除了最低有效位(LSB)之外的所有位都被掩码掉。新的恒等式是 -1,这在二进制补码机器上应该能正常工作,因为所有位都将被设置为 1。
泛化通用函数现在将解锁 GIL#
泛化通用函数,包括大部分 linalg 模块,现在将解锁 Python 全局解释器锁(GIL)。
np.fft 中的缓存现在在总大小和项数上受限#
np.fft 中加速相同长度连续 FFT 的缓存不再能无限增长。它们已被 LRU(最近最少使用)缓存取代,当达到内存大小或项数限制时,LRU 缓存会自动驱逐不再需要的项。
改进了零宽度字符串/Unicode dtype 的处理#
修复了几个明确不允许零宽度字符串 dtype 数组(即 dtype('S0')
或 dtype('U0')
)的接口,并修复了几个此类 dtype 未正确处理的错误。特别是,更改了 ndarray.__new__
,使其在创建新数组时不再隐式地将 dtype('S0')
转换为 dtype('S1')
(对 unicode 也类似)。
整数通用函数通过 AVX2 向量化#
如果 CPU 在运行时支持,基本的整数通用函数现在使用 AVX2 指令。此功能目前仅在使用 GCC 编译时可用。
np.einsum
中的操作顺序优化#
np.einsum
现在支持 optimize
参数,该参数将优化收缩顺序。例如,np.einsum
将在一次传递中完成链式点积示例 np.einsum(‘ij,jk,kl->il’, a, b, c)
,其复杂度将为 N^4
;然而,当 optimize=True
时,np.einsum
将创建一个中间数组,将复杂度降低到 N^3
,或者有效地实现 np.dot(a, b).dot(c)
。使用中间张量来降低复杂度已应用于通用 einsum 求和表示法。更多详细信息请参阅 np.einsum_path
。
快速排序已改为内省排序#
np.sort
和 np.argsort
的快速排序类型现在是内省排序(introsort),它是一种常规的快速排序,但在进展不足时会切换到堆排序。这保留了快速排序的良好性能,同时将最坏情况下的运行时从 O(N^2)
更改为 O(N*log(N))
。
ediff1d
改进了性能和子类处理#
ediff1d
函数在执行减法时,使用数组而不是扁平迭代器。当 to_begin
或 to_end
不为 None 时,减法会在原地执行,以消除复制操作。一个副作用是某些子类(特别是 astropy.Quantity)的处理得到了改进,因为完整的数组是创建、包装,然后设置起始和结束值,而不是使用 concatenate。
改进了 ndarray.mean
对 float16 数组的精度#
float16 数组的均值计算现在以 float32 精度进行,以提高精度。这对于 Theano 等包应该很有用,在这些包中,float16 的精度足够且其更小的占用空间是可取的。
变更#
fromnumeric.py
中所有类数组方法现在都使用关键字参数调用#
在内部,fromnumeric.py
中的许多类数组方法之前是以位置参数而不是关键字参数调用的,尽管它们的外部签名是关键字参数。这导致下游的 'pandas' 库在 'numpy' 兼容性方面遇到了问题。现在,此模块中的所有类数组方法都改为使用关键字参数调用。
对 np.memmap
对象的运算在大多数情况下返回 NumPy 数组#
以前,对内存映射(memmap)对象的操作会误导性地返回一个 memmap 实例,即使结果实际上并未进行内存映射。例如,arr + 1
或 arr + arr
会返回 memmap 实例,尽管输出数组的内存并未映射。1.12 版本从这些操作中返回普通的 NumPy 数组。
此外,内存映射的约简(例如 .sum(axis=None
) 现在返回一个 NumPy 标量,而不是 0 维内存映射。
警告的堆栈级别增加#
基于 Python 的警告的堆栈级别已提高,因此大多数警告将报告用户代码中引发问题的行,而不是警告本身所在的行。现在已对 stacklevel
的传递进行测试,以确保新警告将接收 stacklevel
参数。
这导致带有“default”或“module”过滤器的警告,对于每个有问题的用户代码行或用户模块显示一次,而不是只显示一次。在 Python 3.4 之前的版本中,这可能导致之前被错误忽略的警告现在出现,这尤其在测试套件中可能令人惊讶。