__sizeof__ str 大于 __sizeof__ 包含该字符串的元组
__sizeof__ str is larger than __sizeof__ a tuple containing that string
以下代码产生给定的输出。
import sys
print('ex1:')
ex1 = 'Hello'
print('\t', ex1.__sizeof__())
print('\nex2:')
ex2 = ('Hello', 53)
print('\t', ex2.__sizeof__())
输出:
ex1:
54
ex2:
40
为什么 __sizeof__()
在考虑第二个元素时打印出较小的结果?输出不是应该更大吗?我从 this answer 中意识到我应该使用 sys.getsizeof()
,但这种行为似乎仍然很奇怪。我正在使用 Python 3.5.2
.
另外,正如@Herbert所指出的,'Hello'
比('Hello',)
占用更多的内存,这是一个tuple
。这是为什么?
这是因为 tuple
对象(我很确定所有容器除了字符串)通过包含实际大小来评估它们的大小 而不是 它们各自的内容,而是通过计算指向 PyObject
s 的指针的大小乘以它们包含的元素。也就是说,它们持有指向所包含的(通用)PyObject
的指针,这就是影响其整体大小的原因。
这在 Data Model chapter of the Python Reference 手册中有所暗示:
Some objects contain references to other objects; these are called containers. Examples of containers are tuples, lists and dictionaries. The references are part of a container’s value.
(我强调的是参考这个词。)
In PyTupleType
, a struct where the information on the tuple
type is contained, we see that the tp_itemsize
字段的值是 sizeof(PyObject *)
:
PyTypeObject PyTuple_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"tuple",
sizeof(PyTupleObject) - sizeof(PyObject *),
sizeof(PyObject *), // <-- sizeof pointer to PyObject's
32
bit 构建和 Python 的 64
bit 构建有一个 sizeof(PyObject *)
等于 8 个字节。
这是要乘以 tuple
实例中包含的项目数的值。当我们查看 object_size
时,tuple
继承自 object
的 __sizeof__
方法(检查 object.__sizeof__ is tuple.__sizeof__
),我们清楚地看到:
static PyObject *
object_sizeof(PyObject *self, PyObject *args)
{
Py_ssize_t res, isize;
res = 0;
isize = self->ob_type->tp_itemsize;
if (isize > 0)
res = Py_SIZE(self) * isize; // <-- num_elements * tp_itemsize
res += self->ob_type->tp_basicsize;
return PyLong_FromSsize_t(res);
}
看看 isize
(从 tp_itemsize
获得)如何乘以 Py_SIZE(self)
,这是另一个获取 ob_size
值的宏 指示tuple
.
中的元素数量
这就是为什么,即使我们在元组实例中创建了一个有点大的字符串:
t = ("Hello" * 2 ** 10,)
其中的元素大小为:
t[0].__sizeof__() # 5169
元组实例的大小:
t.__sizeof__() # 32
等于里面只有"Hello"
的那个:
t2 = ("Hello",)
t[0].__sizeof__() # 54
t2.__sizeof__() # 32 Tuple size stays the same.
对于字符串,每个单独的字符都会增加从 str.__sizeof__
返回的值。这与 tuple
仅存储指针这一事实一起,给人一种误导的印象,即 "Hello"
的大小大于包含它的元组。
为了完整起见,unicode__sizeof__
是计算这个的那个。它实际上只是将字符串的长度乘以字符大小(这取决于字符是 1
、2
和 4
字节字符的类型)。
我对元组唯一不明白的是为什么它的基本大小(由 tb_basicsize
表示)被列为 sizeof(PyTupleObject) - sizeof(PyObject *)
。这从返回的总大小中减少了 8
字节;我还没有找到任何解释。
以下代码产生给定的输出。
import sys
print('ex1:')
ex1 = 'Hello'
print('\t', ex1.__sizeof__())
print('\nex2:')
ex2 = ('Hello', 53)
print('\t', ex2.__sizeof__())
输出:
ex1:
54
ex2:
40
为什么 __sizeof__()
在考虑第二个元素时打印出较小的结果?输出不是应该更大吗?我从 this answer 中意识到我应该使用 sys.getsizeof()
,但这种行为似乎仍然很奇怪。我正在使用 Python 3.5.2
.
另外,正如@Herbert所指出的,'Hello'
比('Hello',)
占用更多的内存,这是一个tuple
。这是为什么?
这是因为 tuple
对象(我很确定所有容器除了字符串)通过包含实际大小来评估它们的大小 而不是 它们各自的内容,而是通过计算指向 PyObject
s 的指针的大小乘以它们包含的元素。也就是说,它们持有指向所包含的(通用)PyObject
的指针,这就是影响其整体大小的原因。
这在 Data Model chapter of the Python Reference 手册中有所暗示:
Some objects contain references to other objects; these are called containers. Examples of containers are tuples, lists and dictionaries. The references are part of a container’s value.
(我强调的是参考这个词。)
In PyTupleType
, a struct where the information on the tuple
type is contained, we see that the tp_itemsize
字段的值是 sizeof(PyObject *)
:
PyTypeObject PyTuple_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"tuple",
sizeof(PyTupleObject) - sizeof(PyObject *),
sizeof(PyObject *), // <-- sizeof pointer to PyObject's
32
bit 构建和 Python 的 64
bit 构建有一个 sizeof(PyObject *)
等于 8 个字节。
这是要乘以 tuple
实例中包含的项目数的值。当我们查看 object_size
时,tuple
继承自 object
的 __sizeof__
方法(检查 object.__sizeof__ is tuple.__sizeof__
),我们清楚地看到:
static PyObject *
object_sizeof(PyObject *self, PyObject *args)
{
Py_ssize_t res, isize;
res = 0;
isize = self->ob_type->tp_itemsize;
if (isize > 0)
res = Py_SIZE(self) * isize; // <-- num_elements * tp_itemsize
res += self->ob_type->tp_basicsize;
return PyLong_FromSsize_t(res);
}
看看 isize
(从 tp_itemsize
获得)如何乘以 Py_SIZE(self)
,这是另一个获取 ob_size
值的宏 指示tuple
.
这就是为什么,即使我们在元组实例中创建了一个有点大的字符串:
t = ("Hello" * 2 ** 10,)
其中的元素大小为:
t[0].__sizeof__() # 5169
元组实例的大小:
t.__sizeof__() # 32
等于里面只有"Hello"
的那个:
t2 = ("Hello",)
t[0].__sizeof__() # 54
t2.__sizeof__() # 32 Tuple size stays the same.
对于字符串,每个单独的字符都会增加从 str.__sizeof__
返回的值。这与 tuple
仅存储指针这一事实一起,给人一种误导的印象,即 "Hello"
的大小大于包含它的元组。
为了完整起见,unicode__sizeof__
是计算这个的那个。它实际上只是将字符串的长度乘以字符大小(这取决于字符是 1
、2
和 4
字节字符的类型)。
我对元组唯一不明白的是为什么它的基本大小(由 tb_basicsize
表示)被列为 sizeof(PyTupleObject) - sizeof(PyObject *)
。这从返回的总大小中减少了 8
字节;我还没有找到任何解释。