NumPy 是 Python 科学计算的基础包。
它是一个 Python 库(library),提供了一个多维数组对象、各种派生对象(例如掩码数组和矩阵),以及用于对数组进行快速操作的各种例程,包括数学、逻辑、形状操作、排序、选择、I/O 、离散傅立叶变换、基本线性代数、基本统计运算、随机模拟等等。
NumPy 包的核心是 ndarray 对象。这封装了同构数据类型的 n 维数组,许多操作在编译代码中执行以提高性能。 NumPy 数组和标准 Python 序列之间有几个重要的区别:
关于序列大小和速度的要点在科学计算中尤为重要。作为一个简单的例子,考虑将一维序列中的每个元素与另一个相同长度序列中的相应元素相乘的情况。如果数据存储在两个 Python 列表 a 和 b 中,我们可以遍历每个元素:
c = [ ]
for i in range(len(a)):
c.append(a[i]*b[i])
这会产生正确的答案,但是如果 a 和 b 都包含数百万个数字,我们将为 Python 中循环的低效率付出代价。
我们可以在 C 中通过编写更快地完成相同的任务(为清楚起见,我们忽略了变量声明和初始化、内存分配等)
for (i = 0; i < rows; i++):{
c[i] = a[i]*b[i];
}
这节省了解释 Python 代码和操作 Python 对象所涉及的所有开销,但代价是从 Python 编码中获得的好处。此外,所需的编码工作随着数据维度的增加而增加。例如,在二维数组的情况下,C 代码(如前删节)扩展为
for (i = 0; i < rows; i++):{
for (j = 0; j < columns; j++):{
c[i][j] = a[i][j]*b[i][j];
}
}
NumPy 为我们提供了两全其美的优势:当涉及 ndarray 时,逐元素操作是“默认模式”,但逐元素操作由预编译的 C 代码快速执行。在 NumPy 中
c = a * b
以接近 C 的速度执行前面的示例所做的事情,但是我们期望基于 Python 的东西具有我们期望的代码简单性。事实上,NumPy 习惯用法更简单!最后一个示例说明了 NumPy 的两个功能,它们是其强大功能的基础:矢量化和广播。
矢量化描述了代码中没有任何显式循环、索引等 - 当然,这些事情只是在优化的预编译 C 代码中“在幕后”发生。矢量化代码有很多优点,其中包括:
一般来说,在 NumPy 中,所有操作,不仅仅是算术运算,还有逻辑、位、函数等,都以这种隐式的逐元素方式表现,即它们广播。此外,在上面的例子中,a 和 b 可以是相同形状的多维数组,或者一个标量和一个数组,甚至两个不同形状的数组,前提是较小的数组可以“扩展”到较大的数组的形状以这样的方式产生的广播是明确的。有关广播的详细“规则”,请参阅 basics.broadcasting
NumPy 完全支持面向对象的方法,再次从 ndarray 开始。例如,ndarray 是一个类,拥有许多方法和属性。它的许多方法由最外层 NumPy 命名空间中的函数镜像,允许程序员以他们喜欢的任何范式进行编码。这种灵活性使 NumPy 数组方言和 NumPy ndarray 类成为 Python 中使用的多维数据交换的事实上的语言。