🏠 总目录📚 本教程 附录A · 速查 ←
📑 本页目录(点开跳转)

附录A · 速查

⏱ 26 分钟 | ⭐ 报错原文抄进搜索框查不到?这一页按「你看到的那句话」反查原因


🎯 一句话

这一页不讲道理,只做两件事:把常用 API 按「你想干什么」排好,把报错原文按「你看到什么」排好。

正文各章负责让你懂,这一页负责让你快。所有报错原文都是本机(numpy 2.4.6)真触发出来的,可以直接 Ctrl+F。


🧩 一、API 速查:按用途排,不按字母排

造数组

你想干什么 写法
从列表来 np.array([1,2,3])
全 0 / 全 1 / 未初始化 np.zeros(n) · np.ones(n) · np.empty(n)
等差 np.arange(0,10,2)(不含尾) · np.linspace(0,1,11)(含尾)
和别人同形状 np.zeros_like(a) · np.ones_like(a) · np.full_like(a, 7)
单位阵 / 对角 np.eye(3) · np.diag([1,2,3])

⚠️ np.empty 不是全 0,是没初始化的内存 —— 里面是上一个用户留下的字节。

改形状

你想干什么 写法 视图?
换形状 a.reshape(2,-1) ⚠️ 尽量视图,不行悄悄拷贝
换形状但不许拷贝 a.shape = (2,-1) ✅ 做不到就报错
压平 a.ravel() ✅ 尽量视图
压平并保证独立 a.flatten() ❌ 永远拷贝
转置 a.T · a.transpose(2,0,1) ✅ 只改说明书
加一个长度 1 的轴 a[:, None] · np.expand_dims(a,1) ✅
去掉长度 1 的轴 a.squeeze() ✅
拼接 np.concatenate([a,b], axis=0) · np.stack([a,b]) ❌ 都拷贝

聚合

你想干什么 写法
求和 / 均值 / 标准差 a.sum(axis=0) · a.mean(axis=1) · a.std()
最值 a.max() · a.min()
最值在哪 a.argmax() · np.unravel_index(a.argmax(), a.shape)(多维)
忽略 NaN np.nansum · np.nanmean · np.nanmax
累积 a.cumsum() · a.cumprod()
保住维度好广播 a.sum(axis=1, keepdims=True) ⭐
有没有 / 是不是全部 a.any() · a.all()
计数 np.count_nonzero(mask) · np.bincount(idx)

⭐ keepdims=True 是减少广播出错最有用的一个参数:a - a.mean(axis=1, keepdims=True) 一次就对。

挑元素

你想干什么 写法 视图?
切一块 a[1:3, ::2] ✅
按下标列表挑 a[[0,2,5]] ❌ 拷贝
按条件挑 a[a > 5] ❌ 拷贝
只要下标 np.flatnonzero(mask) · np.where(mask)
三元选择 np.where(cond, x, y)
按条件赋值 a[a < 0] = 0 就地改
夹住范围 np.clip(a, 0, 1)

随机

你想干什么 写法
⭐ 建生成器(推荐) rng = np.random.default_rng(42)
均匀 / 正态 / 整数 rng.random(n) · rng.normal(0,1,n) · rng.integers(0,10,n)
打乱 / 抽样 rng.shuffle(a) · rng.choice(a, 3, replace=False)

⚠️ np.random.seed() 那一套是全局状态,任何库都能改它。新代码一律用 default_rng(详见 10 章)。


🧯 二、⭐ 报错原文 → 原因(全部真触发过)

用法:把你看到的报错开头几个词在这一节 Ctrl+F。

operands could not be broadcast together with shapes (3,4) (3,5)

广播失败。 从右往左对齐后,有一对轴既不相等、也没有一个是 1。 → 打印 a.shape, b.shape 对着 03 章的三条规则 逐轴比。 最常见的真实原因:忘了 keepdims=True,或者某个轴被 squeeze 掉了。

setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions.

你喂了一个「锯齿」嵌套列表(各行长度不同),比如 np.array([[1,2],[3]])。 → 要么补齐成矩形,要么用 dtype=object(但那样就没有向量化了)。

The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

你把一个数组当成了 True/False。 最常见的三种写法:

if arr: ...              # ❌
if arr > 0: ...          # ❌
if (a > 3) and (a < 8):  # ❌ and/or 对数组无效

→ 分别改成 if arr.any():、if (arr > 0).all():、(a > 3) & (a < 8)。 ⚠️ 用 & | 时括号不能省,因为它们的优先级比比较运算符高。

To change to a dtype of a different size, the last axis must be contiguous

.view() 换 dtype 时数组不连续。 通常是转置或跳步切片之后。 → np.ascontiguousarray(a) 先压实一份。机制见 05 章。

cannot reshape array of size 12 into shape (5,3)

元素个数对不上:12 ≠ 15。 → 用 -1 让它自己算一个轴:a.reshape(-1, 3)。

index 5 is out of bounds for axis 0 with size 3

下标越界。 注意它明确告诉了你是哪个轴、那个轴多长。

boolean index did not match indexed array along axis 0; size of axis is 5 but size of corresponding boolean axis is 2

布尔掩码长度和被索引的轴对不上。 通常是掩码在数组变形之后才算的,或者算掩码时用错了轴。

could not convert string to float: np.str_('a')

astype(float) 撞上了非数字字符串。 → 用 pd.to_numeric(..., errors="coerce") 或先 np.isreal 筛一遍。

RuntimeWarning: overflow encountered in exp

⚠️ 这是警告不是报错,程序会带着 inf 继续跑。 阈值取决于精度:

dtype exp(88) exp(89) exp(90) exp(709) exp(710)
float32 1.65e+38 inf inf inf inf
float64 正常 正常 1.22e+39 8.22e+307 inf

⭐ float32 训练时这个坑近在咫尺,float64 要到 710 才炸。 解法永远是先减最大值:np.exp(z - z.max())。详见 09 章 log 域运算。


📋 三、视图还是拷贝

操作 结果 为什么
a[1:3] · a[::2] · a[:, 0] ✅ 视图 偏移等差,能写成一组 strides
a.T · a.transpose() ✅ 视图 只把说明书倒过来
a.reshape(...) ⚠️ 尽量视图 不连续时悄悄拷贝,不报错
a.ravel() ⚠️ 尽量视图 同上
a.flatten() ❌ 永远拷贝 它的契约就是给你一份独立的
a[[0,2,5]] ❌ 拷贝 任意顺序,写不出等差 strides
a[a > 5] ❌ 拷贝 长度要到运行时才知道
a.astype(...) ❌ 拷贝 除非 copy=False 且 dtype 没变
np.concatenate · np.stack ❌ 拷贝 要开新内存

⭐ 判据永远用 np.shares_memory(a, b),⚠️ 不要用 b.base is a —— .base 指向的是最终持有内存的那个、不是上一层(05 章第三节有实测)。


🚦 四、「以为对,其实错」

import numpy as np

# ① == 返回的是数组,不是 bool
print(np.array([1,2]) == np.array([1,3]))   # [ True False]
# → 要一个 bool 就用 np.array_equal(a, b)

# ② NaN 不等于自己
print(np.nan == np.nan)                     # False
# → 判 NaN 只能用 np.isnan(x)

# ③ 整数相除会变浮点
r = np.array([5]) / np.array([2])
print(r, r.dtype)                           # [2.5] float64
# → 要整除用 //

# ④ dtype 会悄悄提升
print((np.ones(1, dtype=np.int8) + np.ones(1, dtype=np.int64)).dtype)   # int64

# ⑤ ⚠️ 但同类型整数溢出【没有任何警告】
a = np.array([100], dtype=np.int8)
print(a + a)                                # [-56]   ← 一声不吭

⑤ 是这一页最值得记的一条:int8 的 100 + 100 得到 -56,连个 RuntimeWarning 都没有。 np.exp 溢出还会警告你一声,整数溢出完全静默。详见 08 章。


🔗 这一章连到哪里

相关的地方 为什么
05 · 内存布局与 stride 「视图还是拷贝」那张表背后的唯一规则:能不能写成一组 strides
08 · 整数 dtype 的真相 静默溢出那条的完整版,含怎么防
09 · log 域运算 exp 溢出表背后的数值稳定性套路
11 · 从 NumPy 到 PyTorch 这些 API 在 torch 里叫什么
ML 基础 · 附录C 手撕代码速查 面试要手写的那十道题,用的就是这一页的 API

✅ 检查点

  1. a.ravel() 和 a.flatten() 差在哪?
  2. 看到 The truth value of an array with more than one element is ambiguous,三种常见写法各怎么改?
  3. np.exp(90) 在 float32 和 float64 下分别是什么?
  4. int8 的 100 + 100 等于几?会不会警告你?
  5. 判断两个数组是不是共享内存,该用什么?为什么不用 .base?
👀 答案
  1. ravel() 尽量返回视图(不连续时才拷贝),flatten() 永远拷贝 —— 它的契约就是给你一份独立的。
  2. if arr: → if arr.any():(或 .all());if arr > 0: → if (arr > 0).all():;if (a>3) and (a<8): → (a > 3) & (a < 8),⚠️ 括号不能省,& 的优先级比比较运算符高。
  3. float32 下是 inf(exp(89) 就炸了,exp(88) 还有 1.65e+38);float64 下是 1.22e+39,要到 exp(710) 才 inf。所以 float32 训练时这个坑近在咫尺。
  4. -56,而且一句警告都没有。⚠️ np.exp 溢出还会给 RuntimeWarning,整数溢出完全静默。
  5. 用 np.shares_memory(a, b)。不用 .base 是因为它指向的是最终持有那块内存的数组、不是上一层 —— a.T.base is a 会给 False,但它们确实共享内存。

🛑 可以停在这里

⚡ 走神救援

⭐ 这一页是查的不是读的,但有几条值得直接背下来。

报错反查:广播对不齐要从右往左逐轴看,⭐ 最常见的真凶是忘了 keepdims=True;「真值不明确」是把数组当成了布尔量,三种改法分别是 .any()、.all()、把 and 换成 &——⚠️ 括号不能省,位运算的优先级比比较运算符高;「最后一维必须连续」是换 dtype 撞上了不连续,压实一份即可。

⭐ 视图还是拷贝只有一条规则:能写成一组等差步长的就是视图。 基础切片和转置是视图;⭐ 花式索引(偏移任意)和布尔掩码(长度运行时才知道)必然拷贝;reshape 尽量给视图、不行就悄悄拷贝且不报错,而 flatten 永远拷贝。

⚠️⭐ 判断共享内存一律用 np.shares_memory,别用 .base——它指向最终持有内存的那个,而不是上一层,所以转置之后拿 .base 去比会得到 False。

数值上三条最容易栽:nan 不等于自身(判它只能用专门的函数);== 返回的是数组不是布尔值;⭐⭐ 最要命的是整数溢出完全静默——小整数类型加一下就绕回负数,连个警告都没有,而浮点溢出好歹还给你一句警告。

⭐ 顺带记住指数函数的两个阈值:单精度到八十几就变成无穷,双精度要到七百多——所以那个「exp(90) 会溢出」的直觉在双精度下是错的。⭐ 解法永远是先减掉最大值。

下一节 👉 回到板块索引

打卡记录保存在你的浏览器里,首页能看到总进度