杂项#
IEEE 754 浮点特殊值#
NumPy 中定义的特殊值:nan, inf,
NaN 可以用作一种简易掩码(如果你不关心原始值是什么)
注意:不能使用相等性来测试 NaN。例如:
>>> myarr = np.array([1., 0., np.nan, 3.])
>>> np.nonzero(myarr == np.nan)
(array([], dtype=int64),)
>>> np.nan == np.nan # is always False! Use special numpy functions instead.
False
>>> myarr[myarr == np.nan] = 0. # doesn't work
>>> myarr
array([ 1., 0., nan, 3.])
>>> myarr[np.isnan(myarr)] = 0. # use this instead find
>>> myarr
array([1., 0., 0., 3.])
其他相关的特殊值函数
isinf(): True if value is inf
isfinite(): True if not nan or inf
nan_to_num(): Map nan to 0, inf to max float, -inf to min float
以下函数与常规函数对应,但 NaN 被排除在结果之外
nansum()
nanmax()
nanmin()
nanargmax()
nanargmin()
>>> x = np.arange(10.)
>>> x[3] = np.nan
>>> x.sum()
nan
>>> np.nansum(x)
42.0
NumPy 如何处理数值异常#
默认情况下,对于 invalid
、divide
和 overflow
会触发 'warn'
,对于 underflow
则会 'ignore'
。但这些设置可以更改,并且可以为不同类型的异常单独设置。不同的行为包括:
‘ignore’ : 异常发生时不做任何处理。
‘warn’ : 打印 RuntimeWarning(通过 Python 的
warnings
模块)。‘raise’ : 抛出 FloatingPointError。
‘call’ : 调用使用 seterrcall 函数指定的函数。
‘print’ : 直接向
stdout
打印警告。‘log’ : 将错误记录到由 seterrcall 指定的 Log 对象中。
这些行为可以针对所有类型的错误或特定错误进行设置
all : 适用于所有数值异常
invalid : 当生成 NaN 时
divide : 除以零(也包括整数!)
overflow : 浮点溢出
underflow : 浮点下溢
请注意,整数除以零由相同的机制处理。这些行为是按线程设置的。
示例#
>>> oldsettings = np.seterr(all='warn')
>>> np.zeros(5,dtype=np.float32)/0.
Traceback (most recent call last):
...
RuntimeWarning: invalid value encountered in divide
>>> j = np.seterr(under='ignore')
>>> np.array([1.e-100])**10
array([0.])
>>> j = np.seterr(invalid='raise')
>>> np.sqrt(np.array([-1.]))
Traceback (most recent call last):
...
FloatingPointError: invalid value encountered in sqrt
>>> def errorhandler(errstr, errflag):
... print("saw stupid error!")
>>> np.seterrcall(errorhandler)
>>> j = np.seterr(all='call')
>>> np.zeros(5, dtype=np.int32)/0
saw stupid error!
array([nan, nan, nan, nan, nan])
>>> j = np.seterr(**oldsettings) # restore previous
... # error-handling settings
与 C 接口#
仅对各种选择进行概述。关于每种选择如何工作的细节很少。
裸机,手动封装您自己的 C 代码。
优点
高效
不依赖其他工具
缺点
学习成本高
需要学习 Python C API 基础知识
需要学习 NumPy C API 基础知识
需要学习如何处理引用计数并熟练掌握。
引用计数通常难以正确处理。
处理不当会导致内存泄漏,甚至更糟的是,段错误
Cython
优点
避免学习 C API
无需处理引用计数
可以用伪 Python 编写代码并生成 C 代码
也可以与现有 C 代码接口
应该能使您免受 Python C API 变更的影响
已成为科学 Python 社区事实上的标准
对数组提供快速索引支持
缺点
可以编写非标准形式的代码,这可能会过时
不如手动封装灵活
ctypes
优点
Python 标准库的一部分
适用于与现有共享库接口,特别是 Windows DLL
避免 API/引用计数问题
良好的 NumPy 支持:数组在其 ctypes 属性中拥有所有这些
a.ctypes.data a.ctypes.data_as a.ctypes.shape a.ctypes.shape_as a.ctypes.strides a.ctypes.strides_as缺点
不能用于编写转换为 C 扩展的代码,只是一种封装工具。
SWIG(自动封装生成器)
优点
存在已久
支持多种脚本语言
支持 C++
适用于封装大型(多函数)现有 C 库
缺点
在 Python 和 C 代码之间生成大量代码
可能导致性能问题,几乎无法优化消除
接口文件可能难以编写
不一定能避免引用计数问题或需要了解 API
Psyco
优点
通过类似 JIT 的优化将纯 Python 代码转换为高效机器代码
优化良好时速度非常快
缺点
仅限于 Intel 平台(Windows?)
对 NumPy 作用不大?
与 Fortran 接口:#
封装 Fortran 代码的明确选择是 f2py。
Pyfort 是一种较旧的替代方案,但已不再受支持。Fwrap 是一个较新的项目,曾看起来很有前景,但已不再开发。
与 C++ 接口:#
Cython
CXX
Boost.python
SWIG
SIP(主要用于 PyQT)