gpt4 book ai didi

python - 为什么 SimpleNamespace 的大小与空类的大小不同?

转载 作者:行者123 更新时间:2023-12-01 00:34:42 24 4
gpt4 key购买 nike

考虑以下几点:

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 个字节的大小似乎恰到好处。

最佳答案

考虑以下具有不同大小的类:

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

关于python - 为什么 SimpleNamespace 的大小与空类的大小不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42078921/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com