请考虑以下事项:
In [1]: import types
In [2]: class A:
...: pass
...:
In [3]: a1 = A()
In [4]: a1.a, a1.b, a1.c = 1, 2, 3
In [5]: a2 = types.SimpleNamespace(a=1,b=2,c=3)
In [6]: sys.getsizeof(a1)
Out[6]: 56
In [7]: sys.getsizeof(a2)
Out[7]: 48
这种尺寸差异来自哪里?看着:
In [10]: types.__file__
Out[10]: '/Users/juan/anaconda3/lib/python3.5/types.py'
我发现:
import sys
# Iterators in Python aren't a matter of type but of protocol. A large
# and changing number of builtin types implement *some* flavor of
# iterator. Don't check the type! Use hasattr to check for both
# "__iter__" and "__next__" attributes instead.
def _f(): pass
FunctionType = type(_f)
LambdaType = type(lambda: None) # Same as FunctionType
CodeType = type(_f.__code__)
MappingProxyType = type(type.__dict__)
SimpleNamespace = type(sys.implementation)
好吧,好吧,这里什么都没有:
>>> import sys
>>> sys.implementation
namespace(cache_tag='cpython-35', hexversion=50660080, name='cpython', version=sys.version_info(major=3, minor=5, micro=2, releaselevel='final', serial=0))
>>> type(sys.implementation)
<class 'types.SimpleNamespace'>
我好像在追逐自己的尾巴。
我能够找到this related question,但没有回答我的特定查询。
我在64位系统上使用CPython 3.5。对于某些错误的引用,这8个字节似乎是正确的大小,我无法指出。
答案 0 :(得分:4)
考虑以下具有不同大小的类:
class A_dict:
pass
class A_slot_0:
__slots__ = []
class A_slot_1:
__slots__ = ["a"]
class A_slot_2:
__slots__ = ["a", "b"]
每个都有不同的基本内存占用:
>>> [cls.__basicsize__ for cls in [A_dict, A_slot_0, A_slot_1, A_slot_2]]
>>> [32, 16, 24, 32]
为什么呢?在type_new
(在typeobject.c
中)的源代码中,它负责创建基础类型并计算实例的基本大小,我们看到tp_basicsize
计算为:
tp_basicsize
(object
... 16字节); sizeof(PyObject *)
; sizeof(PyObject *)
,则__dict__
; sizeof(PyObject *)
,则__weakref__
; 普通类(例如A_dict
)将定义__dict__
和__weakref__
,而带插槽的类默认情况下不会__weakref__
。因此,普通A_dict
的大小是32个字节。您可以认为它实际上由PyObject_HEAD
加上两个指针组成。
现在,考虑一个SimpleNamespace
,它在namespaceobject.c
中定义。这里的类型很简单:
typedef struct {
PyObject_HEAD
PyObject *ns_dict;
} _PyNamespaceObject;
和tp_basicsize
被定义为sizeof(_PyNamespaceObject)
,使得它比普通对象大一个指针,因而是24个字节。
这里的差异实际上是A_dict
为弱引用提供了支持,而types.SimpleNamespace
却没有。
>>> weakref.ref(types.SimpleNamespace())
TypeError: cannot create weak reference to 'types.SimpleNamespace' object