在这种情况下,任何Python对象都实现为带有一些字段的C结构。包含引用计数和指向对象类型的指针的16字节header始终存在于该结构上。这至少是64位股票cpython3.x的情况,我的问题是有限的。你知道吗
出于学术目的和乐趣,我正在搜索一个函数print_object(obj)
,它打印出传递对象obj
的底层struct
。你知道吗
就实现而言,最简单的Python对象可能是float
,它只是附加到前面提到的头的一个C double
。在这个简单的例子中,我可以使用ctypes
和struct
模块编写自己的函数:
import collections, ctypes, struct, sys
header_fields = ['refcount', 'typeptr']
Float = collections.namedtuple('Float', header_fields + ['value'])
def print_object(obj):
ptr = id(obj)
size = sys.getsizeof(obj)
byterep = ctypes.string_at(ptr, size)
header = struct.unpack('qq', byterep[:16])
if isinstance(obj, float):
obj_struct = Float(*header, *struct.unpack('d', byterep[16:]))
elif isinstance(obj, int):
...
print(obj_struct)
# Try it out
a = 1.23
print_object(a)
print('The typeptr should be equal to', id(float))
print('\nNow the refcount should have increased by 1:')
b = a
print_object(a)
本质上,这个函数读取对象的底层内存,并将C struct
的副本构建为Python namedtuple
,有效地重新表示Python本身。代码应该在python3.5及更高版本上运行。它打印出来了
Float(refcount=5, typeptr=140429307606720, value=1.23)
The typeptr should be equal to 140429307606720Now the refcount should have increased by 1:
Float(refcount=6, typeptr=140429307606720, value=1.23)
上面的print_object
函数对float
非常有用,同样的方法可以扩展到(我想是吧?)所有其他类型。有没有任何库(甚至Python标准库)包含这样的功能?你知道吗
尝试自动执行此操作的问题是,没有通用的方法来获取Python类型的布局。见鬼,甚至没有一个通用的方法来判断这个结构有多大。另外,使用
class
语句创建的类型并不完全使用struct
作为其实例,尽管它们的工作方式大多类似于结构。你知道吗您需要自己为任何想要使用的类型提供结构定义,并且仍然需要对具有特别奇怪表示的
int
和str
等类型进行自定义处理。你知道吗相关问题 更多 >
编程相关推荐