這是由於這樣的事實: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