如何在Python中获取列表元素指针的地址而非引用对象的地址
获取Python列表中元素指针的地址
在CPython中,列表底层确实是用指针数组(PyObject**)实现的,但Python层面没有直接提供获取这些指针本身地址的API,必须借助底层操作库(比如ctypes)来实现。
实现步骤
- 先定义CPython中列表对象的简化底层结构(仅保留关键字段,对应CPython内部的列表对象结构):
import ctypes class PyListObject(ctypes.Structure): _fields_ = [ ("ob_refcnt", ctypes.c_ssize_t), ("ob_type", ctypes.c_void_p), ("ob_size", ctypes.c_ssize_t), ("ob_item", ctypes.POINTER(ctypes.c_void_p)), # 存储元素指针的数组 ("allocated", ctypes.c_ssize_t) ]
- 将Python列表对象转换为底层结构体实例,进而访问指针数组中每个元素的地址:
a = [1, 2] # 获取列表对象的底层内存指针 list_ptr = ctypes.cast(id(a), ctypes.POINTER(PyListObject)) # 遍历列表元素,获取每个指针本身的地址 for i in range(list_ptr.contents.ob_size): # 获取列表中第i个元素指针的内存地址 ptr_self_addr = ctypes.addressof(list_ptr.contents.ob_item[i]) # 获取该指针指向的对象地址(即id(a[i])的返回值) ptr_target_addr = list_ptr.contents.ob_item[i] print(f"列表第{i}个元素指针的地址: {ptr_self_addr:#x}") print(f"该指针指向的对象地址(id): {ptr_target_addr:#x}\n")
关键说明
id(a)返回的是列表对象自身的内存地址,通过ctypes.cast将其转换为PyListObject指针后,就能访问内部的ob_item指针数组。ob_item[i]存储的是指向列表元素对象的指针(也就是id(a[i])的返回值),而ctypes.addressof(ob_item[i])才是这个指针本身在内存中的地址——也就是你要找的“元素本身(指针)的地址”。
注意:这种方法完全依赖CPython的底层实现,在PyPy、Jython等其他Python解释器中无效;且Python版本更新可能修改底层结构体定义,使用前需对应目标CPython版本的源码确认结构细节。
内容的提问来源于stack exchange,提问作者run an
相关产品推荐
相关产品推荐

