什么结构是存储在内存中的Python对象?

说我有一个A类:
class A(object):
    def __init__(self, x):
        self.x = x

    def __str__(self):
        return self.x
我使用
sys.getsizeof
来查看
A
的字节数:
>>> sys.getsizeof(A(1))
64
>>> sys.getsizeof(A('a'))
64
>>> sys.getsizeof(A('aaa'))
64
如上面的实验所示,无论
self.x
是什么,
A
对象的大小都是相同的。 所以我想知道python如何在内部存储一个对象?     
已邀请:
这取决于什么样的对象,以及哪个Python实现:-) 在CPython中,这是大多数人在使用ѭ6时使用的,所有Python对象都由C结构表示,
PyObject
。 “存储对象”的所有内容确实存储了
PyObject *
PyObject
结构保存最小的信息:对象的类型(指向另一个
PyObject
的指针)及其引用计数(一个
ssize_t
大小的整数。)C中定义的类型扩展了这个结构,它们需要存储在对象本身中的额外信息,有时分开分配额外的数据。 例如,元组(实现为扩展“PyObject结构”)存储它们的长度以及它们在结构本身内包含的
PyObject
指针(结构在定义中包含1长度数组,但实现分配了一块内存保持
PyTupleObject
结构的正确大小加上与元组应该保持的项目完全相同的数量。)同样,字符串(
PyStringObject
)存储它们的长度,它们的缓存哈希值,一些字符串缓存(“实习”)簿记,以及他们数据的实际char *。因此,元组和字符串是单个内存块。 另一方面,列表(
PyListObject
)存储它们的长度,它们的数据为
PyObject **
,另一个
ssize_t
用于记录它们为数据分配的空间。因为Python在任何地方都存储了7个指针,所以一旦分配了PyObject结构就无法生成它 - 这样做可能需要移动结构,这意味着找到所有指针并更新它们。因为列表可能需要增长,所以它必须与PyObject结构分开分配数据。元组和字符串不能增长,因此它们不需要这样。 Dicts(
PyDictObject
)以相同的方式工作,尽管它们存储密钥,密钥的值和缓存哈希值,而不仅仅是项目。 Dict还有一些额外的开销来容纳小的dicts和专门的查找功能。 但是这些都是C中的类型,你通常可以通过查看C源来查看它们将使用多少内存。用Python而不是C定义的类实例并不那么容易。最简单的情况,经典类的实例,并不是那么困难:它是一个
PyObject
,它将一个
PyObject *
存储到它的类中(这与存储在
PyObject
结构中的类型不同),一个
PyObject *
到它的
__dict__
属性(其中保存所有其他实例属性)和一个
PyObject *
到它的弱列表(由
weakref
模块使用,并且只在必要时才初始化。)实例的
__dict__
通常对实例是唯一的,因此在计算这样一个实例的“内存大小”时你通常也想计算属性字典的大小。但它不必具体针对实例!
__dict__
可以指定就好了。 新式课程复杂化。与经典类不同,新样式类的实例不是单独的C类型,因此它们不需要单独存储对象的类。它们确实有
__dict__
和weakreflist引用的空间,但与经典实例不同,它们不需要任何属性的
__dict__
属性。如果类(及其所有基类)使用
__slots__
来定义严格的属性集,并且这些属性都没有命名为
__dict__
,则实例不允许任意属性,也不分配dict。另一方面,由
__slots__
定义的属性必须存储在某处。这是通过直接在PyObject结构中存储这些属性值的
PyObject
指针来完成的,就像用C语言编写的类型一样。无论属性是否设置,
__slots__
中的每个条目都将占用一个
PyObject *
。 。 所有这一切,问题仍然存在,因为Python中的所有东西都是一个对象,而拥有一个对象的所有内容都只是一个引用,有时很难在对象之间绘制线条。两个对象可以引用相同的数据位。他们可能只拥有该数据的两个引用。摆脱两个对象也摆脱了数据。他们都拥有这些数据吗?只有其中一个,但如果是这样,哪一个?或者你会说他们拥有一半的数据,即使摆脱一个对象不会释放一半的数据? Weakrefs可以使这更加复杂:两个对象可以引用相同的数据,但删除其中一个对象可能会导致另一个对象也摆脱对该数据的引用,导致数据被清除。 幸运的是,常见的情况很容易弄明白。有一些用于Python的内存调试器可以很好地跟踪这些事情,比如heapy。只要您的类(及其基类)相当简单,您就可以对有多少内存进行有根据的猜测 - 特别是在大量情况下。如果您真的想知道数据结构的确切大小,请咨询CPython源代码;大多数内置类型都是
Include/<type>object.h
中描述的简单结构,并在
Objects/<type>object.c
中实现。 PyObject结构本身在
Include/object.h
中描述。请记住:它一直指向下方;那些也占用了房间。     
在新类实例的情况下,getsizeof()返回由Py函数PyInstance_New()返回的PyObject引用的大小 如果你想要一个所有对象大小的列表检查这个。     

要回复问题请先登录注册