这是由于这样的事实:tuple
对象(我敢肯定,除了从字符串中的所有容器)通过包括各自含量的实际尺寸,而是通过计算尺寸评估其大小不指向PyObject
s指示它们包含的元素。也就是说,他们持有指向包含(通用)PyObject
的指针,这就是它的总体规模。
这在Data Model chapter of the Python Reference手册被暗示:
某些对象包含引用对其他对象;这些被称为容器。容器的例子是元组,列表和字典。引用是容器值的一部分。
(我强调这个词引用)
In PyTupleType
,其中在tuple
类型的信息都包含一个结构,我们看到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
位构建和64
位建立的Python有sizeof(PyObject *)
等于8个字节。
这是要乘以tuple
实例中包含的项目数量的值。当我们看object_size
的__sizeof__
方法tuple
期从object
继承(检查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
字节;我还没有找到任何解释(尚未)。
你的第一个对象不是一个元组,它是括号内的一个字符串。 – Kasramvd