![](/img/trans.png)
[英]What is the difference between SimpleNamespace and empty class definition?
[英]Why does SimpleNamespace have a different size than that of an empty class?
考慮以下:
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'>
我好像在追逐自己的尾巴。
我能夠找到這個相關的問題 ,但沒有回答我的特定查詢。
我在64位系統上使用CPython 3.5。 對於某些錯誤的引用,這8個字節似乎是正確的大小,我無法指出。
請考慮以下具有不同大小的類:
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 *)
; __dict__
則為sizeof(PyObject *)
; __weakref__
則為sizeof(PyObject *)
; 像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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.