NumPy切片默认返回视图而非副本,共享原始数组内存,修改视图会直接影响原数组;纯切片(如arr[2:5]、arr[:, ::2])是视图,而高级索引(如arr[[0,2]])返回副本。

因为 NumPy 切片默认返回的是视图(view),不是副本(copy)——它共享原始数组的内存,任何就地修改都会直接写入原数据块。
切片是视图,不是副本
Python 原生列表切片会新建对象,而 NumPy 为性能牺牲了“直觉”:只要用 :、start:stop:step 或逗号分隔的纯切片(如 arr[2:5, ::2]),返回的就是视图。它不复制数据,只调整 offset 和 strides 描述“从哪看、怎么看”。
-
sub = arr[100:200]后,sub.base is arr通常为 True -
sub.data.ptr == arr.data.ptr大概率成立(除非跨步导致非连续) - 多层切片如
arr[5:15][::3]仍是视图,base还连着最原始数组
哪些操作会意外触发修改?
你以为在改局部变量,其实是在改原数组内存。典型陷阱包括:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 赋值语句写成
sub = arr[2:5]; sub[:] = 99——sub[:]是就地写入,原数组第 2~4 位变 99 - 误用
sub = arr[:, [1]](带方括号的整数列表):这已是高级索引,返回副本;但若写成sub = arr[:, 1](单个整数),就是视图,改sub就改原数组第 1 列 - 函数内返回切片后,调用方拿去长期持有:视图强引用原数组,大数组无法被 GC 回收
为什么 .copy() 不总管用?
不是所有 copy 都等价。容易忽略的关键点:
-
arr[10:20].copy()安全;但arr[10:20].copy(order='C')多余,除非你真在调优内存布局 - 如果原数组设为只读:
arr.setflags(write=False),哪怕拿到的是视图,sub[:] = x也会直接报ValueError: assignment destination is read-only - 高级索引(如
arr[[0, 2, 4]]、arr[arr > 5]、arr[[0, 1], :])天然返回副本,但链式写法如B[i_b][ij_b] = True会先取副本再赋值,原数组B不变
真正危险的不是切片本身,而是没意识到它背后那块共享内存——尤其当数据量大、逻辑嵌套深、或跨函数传递时,一个 [:] 就可能让上游静默崩塌。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










