You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何不同Numpy数组的data属性返回相同内存地址?

关于Numpy ndarray.data返回相同内存对象的疑问

问题场景

用户创建了以下Numpy数组并打印ndarray.data:

import numpy as np

a = np.array([[1,2,3],[1,2,3]])    # 2d整数数组
b = np.array([[1,2,3],[1,2,5.0]])  # 2d浮点数数组
c = np.array([1,2,3,4,5,6,7,8,9])  # 1d整数数组
d = np.array([10,20,30])           # 另一个1d整数数组

# 打印指向数组数据起始位置的Python buffer对象
print(a.data)
print(b.data)
print(c.data)
print(d.data)

根据文档描述,ndarray.data应返回指向数组数据起始位置的Python buffer对象,预期每个数组的内存地址不同,但实际输出为:

<memory at 0x000001EAE8B7CAD0>
<memory at 0x000001EAE8B7CAD0>
<memory at 0x000001EAE98E8A00>
<memory at 0x000001EAE98E8A00>

前两个数组的buffer对象地址相同,后两个也相同,疑问:Numpy是根据数组维度推断内存buffer对象指针吗?生成相似地址的规则是什么?


解答

核心误区:混淆了两个地址

你看到的<memory at 0x...>是Python memoryview对象本身的内存地址,不是数组实际数据在内存中的地址。这是两个完全不同的概念:

  • 数组实际数据的地址:是Numpy在堆上分配的、存储数组元素的内存块起始地址
  • memoryview对象的地址:是Python为这个视图对象分配的小内存块地址,仅用于指向数组数据

为什么会出现相同地址?

这和Numpy无关,是Python的垃圾回收与内存复用机制导致的:

  • 当你执行print(a.data)时,Numpy会临时创建一个memoryview对象,打印完成后这个对象没有被任何变量引用,会被Python的垃圾回收器标记为可回收
  • 当后续执行print(b.data)时,Python的内存分配器会优先复用之前被回收的memoryview对象的内存空间,所以新创建的memoryview对象会使用和之前相同的地址

如果你把每个memoryview对象保存下来(避免被回收),就会看到所有地址都不同:

import numpy as np

a = np.array([[1,2,3],[1,2,3]])
b = np.array([[1,2,3],[1,2,5.0]])
c = np.array([1,2,3,4,5,6,7,8,9])
d = np.array([10,20,30])

# 保存memoryview对象,防止被垃圾回收
mv_a = a.data
mv_b = b.data
mv_c = c.data
mv_d = d.data

print(mv_a)
print(mv_b)
print(mv_c)
print(mv_d)

如何查看数组实际数据的内存地址?

要获取数组元素存储的真实内存地址,可以用以下两种方式:

  1. 使用__array_interface__属性:
print(a.__array_interface__['data'][0])  # 输出数组a数据的起始地址
print(b.__array_interface__['data'][0])  # 输出数组b数据的起始地址
  1. 使用ctypes.data属性:
print(a.ctypes.data)
print(b.ctypes.data)

这两种方式得到的地址才是数组实际数据的内存位置,每个数组的这个地址都是不同的(除非数组是视图或者共享内存)。


内容的提问来源于stack exchange,提问作者darren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:31:41