不動如山的 Tuple
Python 裡的 Tuple 是一種不可變的(Immutable)資料結構,它可以用來儲存多個元素,並且可以透過索引值來存取這些元素。Tuple 跟串列有點像,但是 Tuple 是不可變的,也就是說,一旦 Tuple 被建立之後,就不能再新增、刪除或修改裡面的元素。這個章節就來看看它是怎麼設計的,還有哪些有趣的特性。
Tuple 的設計
檔案:Include/cpython/tupleobject.h
typedef struct {
PyObject_VAR_HEAD
PyObject *ob_item[1];
} PyTupleObject;
如果各位是從前面看到這個章節的話,應該對這個結構不陌生了。PyTupleObject
結構的一開頭也有像串列一樣的 PyObject_VAR_HEAD
,然後還有一個 ob_item
成員,主要用來存放 Tuple 中的元素。只是,為什麼這裡是寫 ob_item[1]
而不像 PyListObject
用 **ob_items
?這個 [1]
又是什麼意思?
這是一個 C 語言的技巧,稱為「彈性陣列成員(Flexible Array Member)」,這樣的寫法可以讓結構的最後一個成員是一個未知大小的陣列,雖然看起來像是一個只有一個元素,但實際上它可以容納任意數量的元素,而且所有元素都是連續儲存的。這樣的設計可以讓 Tuple 在記憶體中佔用連續的空間,這樣一來,Python 就可以更有效率地存取 Tuple 裡的元素。大概看起來像這樣:
+-------------------+
| PyObject_VAR_HEAD |
+-------------------+
| ob_item[0] |
+-------------------+
| ob_item[1] |
+-------------------+
| ob_item[2] |
+-------------------+
| ... |
+-------------------+
| ob_item[size-1] |
+-------------------+