NumPy 完整教程:从入门到精通
目录
- 什么是 NumPy?
- 为什么使用 NumPy?
- 安装与环境准备
- 核心概念:
ndarray(N维数组对象) - 创建 NumPy 数组
- 数组的基本属性
- 索引与切片
- 数组运算
- 算术运算
- 广播机制
- 聚合函数
- 其他常用数学函数
- 形状操作
reshape()ravel()和flatten()stack()和hstack(),vstack()split()
- 矩阵运算
- 文件操作
- 随机数生成
- 实战案例
- 案例1:替换数组中的特定值
- 案例2:图像处理入门
- 总结与学习资源
什么是 NumPy?
NumPy 是 Numerical Python 的缩写,是 Python 语言中用于科学计算的核心库,它提供了一个强大的 N维数组对象 ndarray,以及各种操作这些数组的函数,这些函数比 Python 原生的列表操作要快几个数量级。

NumPy 就是为 Python 提供了类似 MATLAB 或 R 语言那样的高效数值计算能力。
为什么使用 NumPy?
与 Python 原生的 list 相比,NumPy 有以下巨大优势:
- 性能卓越:NumPy 数组在内存中是连续存储的,并且内部由 C 语言实现,这使得其计算速度非常快,而 Python 列表存储的是对象的指针,存在大量的类型检查和间接调用,速度较慢。
- 内存占用小:NumPy 数组中的元素类型是固定的(如
int32,float64),因此比 Python 列表(每个元素都可以是不同类型)占用更少的内存。 - 丰富的函数库:NumPy 提供了大量用于线性代数、傅里叶变换、随机数生成等领域的数学函数。
- 广播机制:这是 NumPy 一个非常强大的特性,允许不同形状的数组之间进行算术运算。
安装与环境准备
你需要安装 NumPy,最简单的方式是使用 pip:
pip install numpy
为了验证安装是否成功,可以在 Python 解释器或 Jupyter Notebook 中运行以下代码:

import numpy as np # 如果没有报错,说明安装成功 print(np.__version__)
核心概念:ndarray (N维数组对象)
ndarray 是 NumPy 的核心,它是一个所有元素类型相同、固定大小的多维数组。
与 Python list 的关键区别:
- 类型统一:
ndarray中的所有元素必须是相同的数据类型,这使得 NumPy 能够进行高效的内存分配和计算。 - 性能:如上所述,其底层实现是基于 C 的,速度极快。
创建 NumPy 数组
1 从 Python 列表创建
import numpy as np
# 创建一维数组
arr1d = np.array([1, 2, 3, 4, 5])
print("一维数组:\n", arr1d)
# 创建二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("\n二维数组:\n", arr2d)
# 创建三维数组
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n三维数组:\n", arr3d)
2 使用内置函数创建
NumPy 提供了多种函数来创建特定类型的数组,这在初始化数据时非常有用。
# 创建全为 0 的数组
zeros_arr = np.zeros((3, 4)) # 形状为 (3, 4) 的二维数组
print("全0数组:\n", zeros_arr)
# 创建全为 1 的数组
ones_arr = np.ones((2, 3), dtype=int) # 可以指定数据类型
print("\n全1数组:\n", ones_arr)
# 创建单位矩阵
identity_matrix = np.eye(3)
print("\n单位矩阵:\n", identity_matrix)
# 创建指定范围的数组,类似 Python 的 range
range_arr = np.arange(10) # 从 0 到 9
print("\narange数组:\n", range_arr)
# 创建等差数列
linspace_arr = np.linspace(0, 1, 5) # 在 0 到 1 之间生成 5 个点
print("\nlinspace数组:\n", linspace_arr)
# 创建随机数组
random_arr = np.random.rand(2, 3) # 生成一个 2x3 的 [0, 1) 之间的随机浮点数数组
print("\n随机数组:\n", random_arr)
数组的基本属性
了解这些属性对于理解和使用 NumPy 至关重要。

arr = np.array([[1, 2, 3], [4, 5, 6]])
# ndim: 数组的维度(轴数)
print("维度:", arr.ndim) # 输出 2
# shape: 数组的形状,一个元组,表示每个维度的大小
print("形状:", arr.shape) # 输出 (2, 3)
# size: 数组中元素的总数
print("元素总数:", arr.size) # 输出 6
# dtype: 数组元素的数据类型
print("数据类型:", arr.dtype) # 输出 int64 (取决于你的系统)
# itemsize: 每个元素占用的字节数
print("每个元素字节数:", arr.itemsize) # 输出 8 (int64 占用 8 字节)
索引与切片
NumPy 的索引和切片语法与 Python 列表非常相似,但功能更强大。
1 一维数组
a = np.array([0, 10, 20, 30, 40, 50]) # 获取单个元素 print(a[2]) # 输出 20 # 切片 print(a[1:5]) # 输出 [10 20 30 40] print(a[::2]) # 输出 [ 0 20 40] (步长为2)
2 多维数组
对于多维数组,使用逗号 分隔不同维度的索引或切片。
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 获取单个元素 print(b[0, 1]) # 输出 2 (第0行,第1列) # 获取整行 print(b[1, :]) # 输出 [4 5 6] (等同于 b[1]) # 获取整列 print(b[:, 0]) # 输出 [1 4 7] (第0列的所有行) # 切片获取子数组 print(b[0:2, 1:3]) # 输出: # [[2 3] # [5 6]]
数组运算
这是 NumPy 最强大的部分。
1 算术运算
NumPy 会对数组中的每个元素执行操作(这被称为 向量化)。
a = np.array([1, 2, 3, 4]) b = np.array([10, 20, 30, 40]) print(a + b) # [11 22 33 44] print(a - b) # [-9 -18 -27 -36] print(a * b) # [ 10 40 90 160] print(a / b) # [0.1 0.1 0.1 0.1] print(a ** 2) # [ 1 4 9 16]
2 广播机制
当两个形状不同的数组进行算术运算时,NumPy 会尝试通过“广播”使它们的形状兼容。
广播规则:
- 比较两个数组的维度,从后向前(即从右向左)比较。
- 如果两个维度的大小相等,或者其中一个为1,则它们是兼容的。
- 如果不兼容,则会抛出
ValueError。 - 广播后,形状为1的维度会被“拉伸”以匹配另一个数组的对应维度。
# 标量与数组 a = np.array([1, 2, 3]) print(a * 3) # [ 3 6 9] (标量3被广播到数组a的每个元素) # 数组与一维数组 x = np.array([[1], [2], [3]]) # 形状 (3, 1) y = np.array([4, 5, 6]) # 形状 (3,) # 广播后,x 变成 (3, 3), y 变成 (3, 3) # x: # [[1 1 1] # [2 2 2] # [3 3 3]] # y: # [[4 5 6] # [4 5 6] # [4 5 6]] print(x + y) # 输出: # [[5 6 7] # [6 7 8] # [7 8 9]]
3 聚合函数
这些函数对数组中的元素进行汇总计算。
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 求和
print("总和:", np.sum(arr)) # 输出 21
print("列求和:", np.sum(arr, axis=0)) # 输出 [5 7 9] (对每一列求和)
print("行求和:", np.sum(arr, axis=1)) # 输出 [ 6 15] (对每一行求和)
# 最大值/最小值
print("最大值:", np.max(arr)) # 输出 6
print("列最大值:", np.max(arr, axis=0)) # 输出 [4 5 6]
# 平均值
print("平均值:", np.mean(arr)) # 输出 3.5
# 标准差
print("标准差:", np.std(arr))
# 中位数
print("中位数:", np.median(arr))
4 其他常用数学函数
arr = np.array([0, np.pi/2, np.pi]) # 三角函数 print(np.sin(arr)) # [0.0000000e+00 1.0000000e+00 1.2246468e-16] # 指数和对数 print(np.exp(arr)) # [ 1. 4.81047738 23.14069263] print(np.log(arr)) # 会产生警告,因为 log(0) 是 -inf
形状操作
1 reshape()
改变数组的形状,但元素总数不变。
a = np.arange(12)
print("原始数组:\n", a)
b = a.reshape(3, 4)
print("\nreshape后:\n", b)
# -1 表示自动计算维度
c = a.reshape(2, -1)
print("\n使用-1自动计算:\n", c)
2 ravel() 和 flatten()
将多维数组展平为一维数组。
ravel():返回一个视图(view),如果可能的话,不占用新内存,修改视图会影响原数组。flatten():返回一个副本(copy),一定会占用新内存,修改副本不会影响原数组。
a = np.array([[1, 2], [3, 4]])
# ravel
b = a.ravel()
b[0] = 99
print("修改 ravel 后的 a:\n", a) # a 会改变
# flatten
a = np.array([[1, 2], [3, 4]]) # 重新创建 a
c = a.flatten()
c[0] = 99
print("修改 flatten 后的 a:\n", a) # a 不会改变
3 stack() 和 hstack(), vstack()
拼接数组。
np.stack():沿着一个新轴增加维度来堆叠数组。np.hstack():水平(按列)堆叠数组。np.vstack():垂直(按行)堆叠数组。
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# hstack
print("hstack:\n", np.hstack((a, b))) # [1 2 3 4 5 6]
# vstack
print("vstack:\n", np.vstack((a, b)))
# [[1 2 3]
# [4 5 6]]
# stack
print("stack:\n", np.stack((a, b), axis=0))
# [[1 2 3]
# [4 5 6]]
4 split()
将数组分割成多个子数组。
a = np.arange(9).reshape(3, 3)
print("原始数组:\n", a)
# 水平分割
split_h = np.hsplit(a, 3)
print("\n水平分割为3部分:\n", split_h)
# 垂直分割
split_v = np.vsplit(a, 3)
print("\n垂直分割为3部分:\n", split_v)
矩阵运算
虽然 NumPy 是数组库,但它也提供了专门的矩阵对象 np.matrix(不推荐新项目使用,推荐直接使用 ndarray 并使用 运算符进行矩阵乘法)。
对于 ndarray:
- 是逐元素乘法。
- 是矩阵乘法。
np.dot()也可以用于矩阵乘法。
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 逐元素乘法
print("逐元素乘法:\n", a * b)
# 矩阵乘法
print("矩阵乘法 (@):\n", a @ b)
print("矩阵乘法 (np.dot):\n", np.dot(a, b))
文件操作
NumPy 可以轻松地将数组保存到文件并从文件中读取。
np.save()/np.load():保存和加载.npy文件(二进制,高效)。np.savetxt()/np.loadtxt():保存和加载文本文件(如.txt,.csv),方便人类阅读。
arr = np.arange(10)
# 保存为二进制文件
np.save('my_array.npy', arr)
# 从二进制文件加载
loaded_arr = np.load('my_array.npy')
print("从 .npy 加载:", loaded_arr)
# 保存为文本文件
np.savetxt('my_array.txt', arr, delimiter=',')
# 从文本文件加载
loaded_txt_arr = np.loadtxt('my_array.txt', delimiter=',')
print("从 .txt 加载:", loaded_txt_arr)
随机数生成
np.random 模块功能强大,是机器学习和数据科学的基础。
# 设置随机种子,保证结果可复现
np.random.seed(42)
# 生成标准正态分布随机数
randn_arr = np.random.randn(2, 3)
print("标准正态分布:\n", randn_arr)
# 生成指定范围的随机整数
randint_arr = np.random.randint(0, 10, size=(3, 3))
print("\n随机整数:\n", randint_arr)
# 打乱数组顺序
data = np.arange(10)
np.random.shuffle(data)
print("\n打乱后的数组:\n", data)
实战案例
1 案例1:替换数组中的特定值
假设我们有一个数组,想将其中所有大于 5 的数替换为 1,小于等于 5 的数替换为 0。
Pythonic (但低效) 的方式:
arr = np.random.randint(0, 10, size=(5,)) result = [1 if x > 5 else 0 for x in arr]
NumPy (高效) 的方式: 利用布尔索引和向量化操作。
arr = np.random.randint(0, 10, size=(5,))
print("原始数组:", arr)
# 创建一个与 arr 形状相同的全0数组
result = np.zeros_like(arr)
# 找出大于5的元素的索引,并将这些位置的值设为1
result[arr > 5] = 1
print("处理后的数组:", result)
2 案例2:图像处理入门
一张灰度图可以看作一个二维数组,彩色图是一个三维数组(高 x 宽 x 通道)。
这里我们用 NumPy 创建一个简单的渐变图。
import matplotlib.pyplot as plt
# 创建一个 100x100 的二维数组
# 每一行的值从0到1线性增加
# np.linspace(0, 1, 100) 创建 [0, ..., 1]
# np.tile 将其复制100次,形成100行
gradient = np.tile(np.linspace(0, 1, 100), (100, 1))
# 使用 matplotlib 显示图像
plt.imshow(gradient, cmap='gray')'A Simple Gradient Image')
plt.axis('off') # 关闭坐标轴
plt.show()
总结与学习资源
NumPy 是数据科学和机器学习领域的基石,掌握它的核心概念——ndarray、广播、向量化运算和索引——是通往更高级库(如 Pandas, Scikit-learn, TensorFlow, PyTorch)的必经之路,多动手练习,尝试用 NumPy 重写一些用 Python 原生列表实现的计算任务,你会深刻体会到它的威力。
学习资源:
- 官方文档:NumPy User Guide (最权威,但可能对初学者稍显枯燥)
- Scipy Lecture Notes:Scipy Lecture Notes (非常经典的免费教程,内容详实)
- Real Python:NumPy Tutorial (讲解清晰,示例丰富)
- YouTube:搜索 "NumPy Tutorial",有很多优秀的视频教程,如 Corey Schafer 的系列视频。
- 练习:在 LeetCode 或 Kaggle 上寻找需要数值计算的问题来练习。
