Python NumPy 使用指南入门
- C语言进阶
- 12小时前
- 15热度
- 0评论
ℹ️ 官方文档
• NumPy 官方网站: https://numpy.org/
• 官方文档: https://numpy.org/doc/stable/
• API 参考: https://numpy.org/doc/stable/reference/
• 用户指南: https://numpy.org/doc/stable/user/index.html
• 快速入门: https://numpy.org/doc/stable/user/quickstart.html
• NumPy 官方网站: https://numpy.org/
• 官方文档: https://numpy.org/doc/stable/
• API 参考: https://numpy.org/doc/stable/reference/
• 用户指南: https://numpy.org/doc/stable/user/index.html
• 快速入门: https://numpy.org/doc/stable/user/quickstart.html
什么是 NumPy
NumPy (Numerical Python) 是 Python 科学计算的基础库,提供:
- 高性能的多维数组对象 ndarray
- 用于数组操作的工具
- 线性代数、傅里叶变换、随机数生成等功能
- 与 C/C++/Fortran 代码集成的工具
💡 为什么使用 NumPy?
• 性能: 比 Python 列表快 10-100 倍
• 内存效率: 占用内存更少
• 向量化: 避免显式循环,代码更简洁
• 生态系统: pandas, scikit-learn, TensorFlow 等库的基础
• 性能: 比 Python 列表快 10-100 倍
• 内存效率: 占用内存更少
• 向量化: 避免显式循环,代码更简洁
• 生态系统: pandas, scikit-learn, TensorFlow 等库的基础
Python 标准库 vs NumPy 对比
1. 数据结构对比
| 特性 | Python List | NumPy Array |
|---|---|---|
| 数据类型 | 可以混合类型 | 必须同一类型 |
| 内存布局 | 分散存储(指针数组) | 连续存储 |
| 大小 | 动态可变 | 固定大小(reshape 创建新数组) |
| 性能 | 较慢 | 快 10-100 倍 |
| 内存占用 | 较大 | 较小 |
| 多维支持 | 需要嵌套列表 | 原生支持多维 |
| 向量化操作 | 不支持 | 支持 |
# Python List - 混合类型
py_list = [1, "hello", 3.14, True]
# NumPy Array - 统一类型
import numpy as np
np_array = np.array([1, 2, 3, 4]) # 全部转为同一类型

python list和np array区别
2. 范围生成对比
| 函数 | 参数类型 | 返回类型 | 用途 |
|---|---|---|---|
range(start, stop, step) |
只接收整数 | range 对象(惰性) | 整数序列 |
np.arange(start, stop, step) |
可以接收浮点数 | ndarray | 数值序列 |
np.linspace(start, stop, num) |
浮点数 + 数量 | ndarray | 均匀分布的数值 |
# Python range - 只能整数
python_range = range(0, 10, 2) # [0, 2, 4, 6, 8]
# range(0.0, 10.0, 0.5) # ❌ TypeError
# NumPy arange - 支持浮点数
np_arange = np.arange(0.0, 10.0, 0.5) # ✅ [0.0, 0.5, 1.0, ..., 9.5]
# NumPy linspace - 指定数量而非步长
np_linspace = np.linspace(0, 10, 21) # 21 个均匀分布的点
⚠️ arange 的浮点数陷阱
使用浮点数步长时,由于浮点数精度问题,结果可能不可预测:
使用浮点数步长时,由于浮点数精度问题,结果可能不可预测:
np.arange(0.1, 0.3, 0.1) # 可能是 [0.1, 0.2] 或 [0.1, 0.2, 0.3]
np.linspace(0.1, 0.3, 3) # 更可靠: [0.1, 0.2, 0.3]

numpy范围生成对比
3. 数学函数对比
Python math 模块 |
NumPy | 区别 |
|---|---|---|
math.sin(x) |
np.sin(x) |
math 不能接收数组 |
math.cos(x) |
np.cos(x) |
NumPy 可以接收数组 |
math.exp(x) |
np.exp(x) |
NumPy 支持向量化 |
math.log(x) |
np.log(x) |
NumPy 更快 |
math.sqrt(x) |
np.sqrt(x) |
NumPy 支持广播 |
import math
import numpy as np
# Python math - 只能处理标量
x = 1.5
result = math.sin(x) # ✅ 单个值
# math.sin([1, 2, 3]) # ❌ TypeError: must be real number, not list
# NumPy - 可以处理数组(向量化)
x_array = np.array([0, np.pi/2, np.pi])
result_array = np.sin(x_array) # ✅ [0., 1., 0.]
# 性能对比
import time
# 使用 math 模块(需要循环)
data = list(range(1000000))
start = time.time()
result_math = [math.sin(x) for x in data]
time_math = time.time() - start
# 使用 NumPy(向量化)
data_np = np.arange(1000000)
start = time.time()
result_np = np.sin(data_np)
time_np = time.time() - start
print(f"math 模块: {time_math:.4f}s")
print(f"NumPy: {time_np:.4f}s")
print(f"NumPy 快 {time_math/time_np:.1f} 倍")

python与numpy数学函数对比
4. 列表操作 vs 数组操作
| 操作 | Python List | NumPy Array |
|---|---|---|
| 元素相加 | 列表拼接 | 元素级加法 |
| 元素相乘 | 列表重复 | 元素级乘法 |
| 标量运算 | 需要循环/列表推导 | 直接广播 |
| 条件筛选 | 需要 filter/推导 | 布尔索引 |
# 列表拼接 vs 数组加法
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print(list1 + list2) # [1, 2, 3, 4, 5, 6] - 拼接
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
print(arr1 + arr2) # [5 7 9] - 元素级加法
# 列表重复 vs 数组乘法
print(list1 * 3) # [1, 2, 3, 1, 2, 3, 1, 2, 3] - 重复
print(arr1 * 3) # [3 6 9] - 元素级乘法
# 标量运算
# Python: 需要列表推导
result_list = [x * 2 + 1 for x in list1]
# NumPy: 直接广播
result_array = arr1 * 2 + 1
# 条件筛选
# Python: 需要 filter 或推导
filtered_list = [x for x in list1 if x > 1]
# NumPy: 布尔索引
filtered_array = arr1[arr1 > 1]

列表操作和数组运算
5. 统计函数对比
| 功能 | Python 标准库 | NumPy |
|---|---|---|
| 求和 | sum(list) |
np.sum(arr) 或 arr.sum() |
| 最大值 | max(list) |
np.max(arr) 或 arr.max() |
| 最小值 | min(list) |
np.min(arr) 或 arr.min() |
| 平均值 | statistics.mean() |
np.mean(arr) 或 arr.mean() |
| 中位数 | statistics.median() |
np.median(arr) |
| 标准差 | statistics.stdev() |
np.std(arr) 或 arr.std() |
| 方差 | statistics.variance() |
np.var(arr) 或 arr.var() |
import statistics
data_list = [1, 2, 3, 4, 5]
data_array = np.array([1, 2, 3, 4, 5])
# Python 标准库
print(sum(data_list)) # 15
print(max(data_list)) # 5
print(statistics.mean(data_list)) # 3.0
print(statistics.stdev(data_list)) # 1.58...
# NumPy - 更简洁,支持多维
print(data_array.sum()) # 15
print(data_array.max()) # 5
print(data_array.mean()) # 3.0
print(data_array.std()) # 1.41... (默认是总体标准差)
# NumPy 支持按轴统计(多维数组)
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
print(matrix.sum(axis=0)) # [5 7 9] - 按列求和
print(matrix.sum(axis=1)) # [6 15] - 按行求和
核心概念
1. ndarray(N 维数组)
⚠️ ndarray 是 NumPy 的核心
ndarray (N-dimensional array) 是一个多维、同类型元素的容器。
ndarray (N-dimensional array) 是一个多维、同类型元素的容器。
关键属性:
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr.shape) # (2, 3) - 形状
print(arr.ndim) # 2 - 维度数
print(arr.size) # 6 - 元素总数
print(arr.dtype) # int64 - 数据类型
print(arr.itemsize) # 8 - 每个元素字节数
print(arr.nbytes) # 48 - 总字节数
创建数组的方法:
# 从列表创建
np.array([1, 2, 3])
# 创建特殊数组
np.zeros((3, 4)) # 全 0
np.ones((2, 3)) # 全 1
np.full((2, 2), 7) # 全 7
np.eye(3) # 单位矩阵
np.empty((2, 3)) # 未初始化(随机值)
# 创建序列
np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
np.linspace(0, 1, 5) # [0., 0.25, 0.5, 0.75, 1.]
# 随机数组
np.random.rand(3, 4) # [0, 1) 均匀分布
np.random.randn(3, 4) # 标准正态分布
np.random.randint(0, 10, (3, 4)) # 随机整数
2. 广播(Broadcasting)
💡 广播机制
广播允许不同形状的数组进行算术运算,NumPy 会自动扩展较小的数组。
广播允许不同形状的数组进行算术运算,NumPy 会自动扩展较小的数组。
广播规则:
- 如果数组维度不同,在较小维度数组的形状前面补 1
- 输出数组的每个维度大小是输入数组该维度的最大值
- 如果输入数组某个维度是 1 或与输出数组对应维度相同,则可以广播
- 如果输入数组某个维度是 1,则沿该维度重复
# 标量广播
arr = np.array([1, 2, 3])
print(arr + 10) # [11, 12, 13]
# 一维数组广播到二维
arr_2d = np.array([[1, 2, 3],
[4, 5, 6]])
arr_1d = np.array([10, 20, 30])
print(arr_2d + arr_1d)
# [[11 22 33]
# [14 25 36]]
# 列向量广播
col = np.array([[1],
[2]])
print(arr_2d + col)
# [[2 3 4]
# [6 7 8]]
# 广播示例:标准化
data = np.random.randn(100, 3)
mean = data.mean(axis=0) # 形状 (3,)
std = data.std(axis=0) # 形状 (3,)
normalized = (data - mean) / std # 广播到 (100, 3)
3. 向量化(Vectorization)
✅ 向量化的优势
向量化操作在 C 层面执行,避免 Python 循环开销,速度快 10-100 倍。
向量化操作在 C 层面执行,避免 Python 循环开销,速度快 10-100 倍。
# ❌ 不推荐:显式循环
result = []
for x in data:
result.append(x ** 2 + 2 * x + 1)
# ✅ 推荐:向量化
data = np.array(data)
result = data ** 2 + 2 * data + 1
# 复杂示例:计算距离矩阵
points = np.random.rand(1000, 2)
# ❌ 慢:双重循环
distances = np.zeros((1000, 1000))
for i in range(1000):
for j in range(1000):
distances[i, j] = np.sqrt(np.sum((points[i] - points[j]) ** 2))
# ✅ 快:向量化(使用广播)
diff = points[:, np.newaxis, :] - points[np.newaxis, :, :]
distances = np.sqrt(np.sum(diff ** 2, axis=2))
4. 索引和切片
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# 基本索引
print(arr[0, 1]) # 2
print(arr[1]) # [5 6 7 8]
# 切片
print(arr[:2, 1:3]) # [[2 3]
# [6 7]]
# 布尔索引
mask = arr > 5
print(arr[mask]) # [6 7 8 9 10 11 12]
# 花式索引
indices = [0, 2]
print(arr[indices]) # [[1 2 3 4]
# [9 10 11 12]]
# 组合索引
print(arr[arr[:, 0] > 1, :2]) # [[5 6]
# [9 10]]
5. 数组变形
arr = np.arange(12)
# reshape - 改变形状(返回视图)
arr_2d = arr.reshape(3, 4)
arr_3d = arr.reshape(2, 2, 3)
# resize - 原地改变形状
arr.resize(3, 4)
# ravel/flatten - 展平为一维
arr_2d.ravel() # 返回视图
arr_2d.flatten() # 返回副本
# transpose - 转置
arr_2d.T
arr_3d.transpose(2, 0, 1) # 指定轴顺序
# 添加/删除维度
arr_new = arr[:, np.newaxis] # 添加新轴
arr_squeezed = np.squeeze(arr_new) # 删除长度为 1 的轴
常用函数分类
1. 数组创建
| 函数 | 说明 | 文档链接 |
|---|---|---|
np.array() |
从列表/元组创建 | 文档 |
np.zeros() |
创建全 0 数组 | 文档 |
np.ones() |
创建全 1 数组 | 文档 |
np.full() |
创建常数数组 | 文档 |
np.eye() |
创建单位矩阵 | 文档 |
np.arange() |
创建等差序列 | 文档 |
np.linspace() |
创建均匀分布序列 | 文档 |
np.logspace() |
创建对数分布序列 | 文档 |
2. 数学函数
| 类别 | 函数 | 说明 |
|---|---|---|
| 三角函数 | sin, cos, tan |
三角函数 |
arcsin, arccos, arctan |
反三角函数 | |
sinh, cosh, tanh |
双曲函数 | |
| 指数对数 | exp, exp2, expm1 |
指数函数 |
log, log2, log10, log1p |
对数函数 | |
| 幂函数 | power, sqrt, square |
幂和平方根 |
| 舍入 | round, floor, ceil, trunc |
舍入函数 |
| 符号 | abs, sign |
绝对值和符号 |
3. 统计函数
| 函数 | 说明 | 文档 |
|---|---|---|
np.mean() |
平均值 | 文档 |
np.median() |
中位数 | 文档 |
np.std() |
标准差 | 文档 |
np.var() |
方差 | 文档 |
np.min(), np.max() |
最小/最大值 | 文档 |
np.argmin(), np.argmax() |
最小/最大值索引 | 文档 |
np.percentile() |
百分位数 | 文档 |
np.corrcoef() |
相关系数 | 文档 |
4. 线性代数
| 函数 | 说明 | 文档 |
|---|---|---|
np.dot() |
点积/矩阵乘法 | 文档 |
np.matmul() / @ |
矩阵乘法 | 文档 |
np.linalg.inv() |
矩阵求逆 | 文档 |
np.linalg.det() |
行列式 | 文档 |
np.linalg.eig() |
特征值和特征向量 | 文档 |
np.linalg.solve() |
求解线性方程组 | 文档 |
5. 随机数生成
| 函数 | 说明 | 文档 |
|---|---|---|
np.random.rand() |
[0, 1) 均匀分布 | 文档 |
np.random.randn() |
标准正态分布 | 文档 |
np.random.randint() |
随机整数 | 文档 |
np.random.choice() |
随机抽样 | 文档 |
np.random.shuffle() |
原地打乱 | 文档 |
np.random.seed() |
设置随机种子 | 文档 |
📝 新的随机数 API
NumPy 1.17+ 推荐使用
NumPy 1.17+ 推荐使用
np.random.Generator:
rng = np.random.default_rng(seed=42)
rng.random((3, 4))
rng.integers(0, 10, size=(3, 4))
6. 数组操作
| 函数 | 说明 | 文档 |
|---|---|---|
np.concatenate() |
连接数组 | 文档 |
np.stack() |
堆叠数组 | 文档 |
np.split() |
分割数组 | 文档 |
np.sort() |
排序 | 文档 |
np.unique() |
去重 | 文档 |
np.where() |
条件选择 | 文档 |
性能对比
内存占用对比
import sys
# Python List
py_list = list(range(1000000))
print(f"List 内存: {sys.getsizeof(py_list) / 1024 / 1024:.2f} MB")
# NumPy Array
np_array = np.arange(1000000)
print(f"NumPy 内存: {np_array.nbytes / 1024 / 1024:.2f} MB")
# 结果示例:
# List 内存: 8.39 MB
# NumPy 内存: 7.63 MB
运算速度对比
import time
size = 1000000
# Python List
py_list = list(range(size))
start = time.time()
result = [x ** 2 for x in py_list]
time_list = time.time() - start
# NumPy Array
np_array = np.arange(size)
start = time.time()
result = np_array ** 2
time_numpy = time.time() - start
print(f"List: {time_list:.4f}s")
print(f"NumPy: {time_numpy:.4f}s")
print(f"NumPy 快 {time_list / time_numpy:.1f} 倍")
# 典型结果:
# List: 0.1234s
# NumPy: 0.0012s
# NumPy 快 102.8 倍
最佳实践
💡 NumPy 使用建议
1. 优先使用向量化操作,避免显式循环
2. 使用视图而非副本(如
3. 预分配数组,避免动态增长
4. 使用合适的数据类型(如
5. 利用广播机制,减少内存占用
6. 使用
7. 使用
1. 优先使用向量化操作,避免显式循环
2. 使用视图而非副本(如
reshape 而非 resize)3. 预分配数组,避免动态增长
4. 使用合适的数据类型(如
float32 而非 float64)5. 利用广播机制,减少内存占用
6. 使用
np.where() 替代条件循环7. 使用
@ 运算符进行矩阵乘法(Python 3.5+)
# ❌ 不推荐
result = []
for i in range(len(arr)):
if arr[i] > 0:
result.append(arr[i] ** 2)
else:
result.append(0)
# ✅ 推荐
result = np.where(arr > 0, arr ** 2, 0)
# ❌ 不推荐:动态增长
result = np.array([])
for i in range(1000):
result = np.append(result, i ** 2)
# ✅ 推荐:预分配
result = np.empty(1000)
for i in range(1000):
result[i] = i ** 2
# ✅ 更好:向量化
result = np.arange(1000) ** 2
参考链接
- NumPy 官方教程: https://numpy.org/doc/stable/user/absolute_beginners.html
- NumPy for MATLAB users: https://numpy.org/doc/stable/user/numpy-for-matlab-users.html
- NumPy Cheat Sheet: https://numpy.org/doc/stable/user/quickstart.html
- SciPy Lecture Notes: https://scipy-lectures.org/
- Python Data Science Handbook: https://jakevdp.github.io/PythonDataScienceHandbook/