Numpy切片与Python列表切片行为差异及底层原理问询
列表与Numpy切片行为差异的技术原理
Python列表的切片机制
Python列表本质是存储Python对象引用的数组,本身不直接持有数据值,仅持有指向各个数据对象的指针。
当你执行[:]切片操作时:
- 会生成一个全新的列表对象,所以你看到
a和b的id不同 - 新列表会复制原列表里所有的引用指针,所以切片后
a[0]和b[0]的id完全一致,指向同一个int对象 - 当你执行
b[0] = -1时,本质是修改新列表第0位的引用指向,让它指向新的int对象-1,这个操作完全不涉及原列表的引用指针,所以原列表不会发生变化。
Numpy数组的切片机制
Numpy数组的核心是「连续同类型内存块 + 视图元信息」的结构:实际的数值全部存在一块独立的连续内存缓冲区里,数组对象本身仅持有这块缓冲区的引用,以及形状、步长、数据偏移量等元信息。
当你执行[:]切片操作时:
- 会生成一个全新的Numpy数组对象,所以你看到
l和p的id不同 - 新数组不会复制底层的内存缓冲区,仅复制元信息,和原数组共享同一块底层数据内存
- 你观测到
id(l[0])和id(p[0])不同,是因为单独取数组元素时,Numpy会把底层缓冲区的数值临时包装成Python标量对象返回,每次取值都会生成新的包装对象,这个id仅对应临时包装对象的地址,和底层数据的实际存储位置无关 - 当你执行
p[0] = -1时,是直接修改共享的底层内存缓冲区里的数值,原数组l也指向同一块内存,所以会同步发生变化。
如果需要Numpy切片修改不影响原数组,主动调用copy()方法强制复制底层内存即可:p = l[:].copy()。
内容的提问来源于stack exchange,提问作者Vivek Vankadaru
相关产品推荐
相关产品推荐

