numpy数组行赋值后对应切片id未按预期变化原因咨询
numpy数组切片索引的id不变现象原理
结论
你观察到的现象完全符合numpy的设计逻辑,第4行的id值没有变化是正常情况,不需要疑惑。
核心原理
你之前的认知适用于Python原生不可变对象(如int、float、str),但numpy数组的索引取值行为和原生对象完全不同:
- 首先你调用
a[0]返回的不是Python原生的数值/列表对象,而是一个numpy数组视图(view),本质是一个ndarray类型的实例,它和原数组a共享底层数据缓冲区。只有基础整数索引、切片索引会返回共享内存的视图,花式索引、布尔索引返回的是独立的数组副本,行为会有差异。 id()函数返回的是你传入的Python对象本身的内存地址,不是对象内部存储数据的缓冲区地址。你执行a[0] = A这类操作时,只是原地修改了该视图对应的数据缓冲区的内容,没有改变a[0]返回的ndarray实例本身的内存地址,所以id不会变化。- 你没有把
a[0]赋值给变量持有时,每次调用a[0]都会生成一个临时的视图对象,调用完id()后这个临时对象会被Python回收。前两次调用id(a[0])时,新生成的临时视图刚好复用了上一次被回收的临时对象的内存空间,所以id相同;中间执行b = [1,2,3]等操作后,那块内存被其他对象占用,第三次生成的临时视图只能分配到新的内存空间,所以id发生了变化。
验证代码
你可以通过以下代码验证逻辑:
import numpy as np a = np.array([[0,1,2],[3,4,5],[6,7,8]]) # 把a[0]赋值给变量持有,避免被回收 row = a[0] print(id(row)) # 输出第一个地址 # 修改行内容 row[:] = [0,0,0] print(id(row)) # 地址和之前完全相同,修改内容不会改变视图对象本身的地址 # 新生成一个视图对象 new_row = a[0] print(id(new_row)) # 新对象地址和之前不同
内容的提问来源于stack exchange,提问作者4cket
相关产品推荐
相关产品推荐

