NumPy
问题
NumPy 的 ndarray 和 Python 列表有什么区别?广播机制是什么?
答案
ndarray vs list
import numpy as np
# Python list:元素类型可不同,存储为指针数组
py_list = [1, 2.0, "three"]
# ndarray:同类型、连续内存、支持向量化运算
arr = np.array([1, 2, 3, 4], dtype=np.float64)
| 特性 | Python list | NumPy ndarray |
|---|---|---|
| 类型 | 任意混合 | 单一类型(dtype) |
| 内存 | 指针数组 | 连续内存块 |
| 运算 | 逐元素循环 | 向量化(C 实现) |
| 速度 | 慢 | 快 10-100x |
向量化运算
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 逐元素运算(无需 for 循环)
c = a + b # [5, 7, 9]
d = a * b # [4, 10, 18]
e = np.dot(a, b) # 32(点积)
# 矩阵运算
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = A @ B # 矩阵乘法
广播(Broadcasting)
当两个数组形状不同时,NumPy 自动扩展维度:
# 规则:从右对齐,维度为 1 或相等才能广播
a = np.array([[1, 2, 3], # shape (2, 3)
[4, 5, 6]])
b = np.array([10, 20, 30]) # shape (3,) → 广播为 (2, 3)
c = a + b
# [[11, 22, 33],
# [14, 25, 36]]
常用操作
# 形状操作
arr = np.arange(12) # [0, 1, ..., 11]
matrix = arr.reshape(3, 4) # 3x4 矩阵
flat = matrix.ravel() # 展平
# 索引与切片
matrix[0, :] # 第一行
matrix[:, 1] # 第二列
matrix[matrix > 5] # 布尔索引
# 聚合
matrix.sum(axis=0) # 按列求和
matrix.mean(axis=1) # 按行求均值
常见面试问题
Q1: NumPy 为什么快?
答案:
- 连续内存:数据紧密排列,CPU 缓存命中率高
- C 实现:核心运算用 C/Fortran 编写,无 Python 解释器开销
- SIMD 指令:利用 CPU 向量化指令并行处理多个数据
- 避免循环:向量化操作替代 Python for 循环
Q2: copy() 和 view() 的区别?
答案:
a = np.array([1, 2, 3, 4])
b = a[1:3] # view(浅拷贝,共享内存)
c = a[1:3].copy() # 深拷贝
b[0] = 99
print(a) # [1, 99, 3, 4]——a 也变了
Q3: C-order 和 F-order 的区别?
答案:
- C-order(行优先,默认):同一行的元素在内存中连续
- F-order(列优先):同一列的元素在内存中连续
遍历时按内存顺序访问性能最好。NumPy 默认 C-order,与 Python 的行循环习惯一致。