np.diag是双向函数,可提取对角线或构造对角矩阵;np.diagonal是单向提取器,支持高维、offset偏移及指定轴,语义更清晰、适用性更广。

diag 和 diagonal 的核心区别在哪
别被名字骗了:np.diag 不是“提取对角线”的专用函数,它其实是双向的:既能从二维数组中取对角线,也能把一维数组“撑成”对角矩阵。而 np.diagonal 才是纯正的对角线提取器,只读不写,且支持更高维数组(比如三维张量的面内对角线)。如果你只想取对角线,优先用 diagonal;如果后续还要反向构造对角矩阵,diag 更顺手。
提取主对角线时为什么有时结果不对
常见错误是直接对非方阵调用 np.diag(arr) 却没注意行为差异:
-
np.diag(arr)对非方阵默认取min(arr.shape[0], arr.shape[1])长度的主对角线,但会静默截断——比如 3×5 矩阵返回长度为 3 的数组,容易误以为漏了数据 -
np.diagonal(arr)行为一致,但更明确:它始终沿第 0、1 轴取对角线,不受是否方阵影响,语义更清晰 - 若想取副对角线(如从右上到左下),必须用
np.diagonal(arr, offset=1)或np.fliplr(arr).diagonal(),np.diag不支持offset参数
三维数组怎么取“面内对角线”
np.diagonal 是唯一能处理三维及以上数组的选项。np.diag 只接受二维或一维输入,遇到三维会直接报错 ValueError: Input must be 1- or 2-d。
例如有形状为 (4, 5, 6) 的数组 a,想对每个 5×6 切片取主对角线(即沿轴 1 和 2):
np.diagonal(a, axis1=1, axis2=2) # 输出 shape=(4, 5)
关键点:
-
axis1和axis2指定哪两个轴构成“面”,不能相同,且索引必须有效 - 结果维度 = 原维度数 − 1,被选中的两轴合并为一个对角线轴
-
np.diag完全不支持这种操作,强行用会立刻失败
性能与内存开销有啥实际差别
两者都返回视图(view)还是副本(copy)?答案是:np.diagonal 在多数常见情况下返回视图(零拷贝),而 np.diag 对二维输入也返回视图,但对一维输入会构造新矩阵(必然拷贝)。
真正要注意的是链式操作:
- 用
np.diagonal(arr)[::2]会触发一次副本(切片视图不可链式索引),而np.diagonal(arr, offset=2)仍保持视图 - 如果只是临时取值、不做修改,
diagonal更轻量;如果后续要赋值回原数组,需确认是否支持(视图可写,副本不行) - 在循环里高频调用时,避免用
np.diag处理非方阵——它内部有隐式 shape 校验,比diagonal略慢
对角线操作看着简单,但维数、方向、视图性这几个点一旦混用,调试起来特别费时间——尤其是从二维扩到三维时,diag 直接失效,而 diagonal 的 axis1/axis2 参数又容易填反。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











