- cpython/Include/cpython/tupleobject.c
- cpython/Include/tupleobject.h
- cpython/Objects/tupleobject.c
The structure of tuple object is more simple than other python object. Obviously, ob_item is an array of PyObject* pointer, all elements will be stored inside the ob_item array, But how exactly each element stored in PyTupleObject? Is the first element begin at the 0 index? What is the resize strategy?
Let's see
t = tuple()
t = ("aa", )
t = ("aa", "bb", "cc", "dd")
ob_size represents the size of PyTupleObject object, because tuple object is immutable, the ob_item is the start address of an array of pointer to PyObject, and the size of this array is ob_size, there's no need for resize operation.
The free_list mechanism used here is more interesting than free_list in list
#define PyTuple_MAXSAVESIZE 20
#define PyTuple_MAXFREELIST 2000
static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];
static int numfree[PyTuple_MAXSAVESIZE];
let's exam what free_list and numfree is we assume that python interpreter don't create/deallocate any tuple object internally during the following code
>>> t = tuple()
>>> id(t)
4458758208
>>> del t
>>> t = tuple()
>>> id(t) # same as previous deleted one
4458758208
>>> t2 = tuple()
>>> id(t2) # same as t
4458758208
>>> t = ("aa", )
>>> id(t)
4459413360
>>> del t
>>> t = ("bb", )
>>> id(t) # it's not repeatable, because I assume that python intepreter don't create/deallocate any tuple object during execution
4459413360
>>> t2 = ("cc", )
>>> del t
>>> del t2
num_free[i] means how many objects left in free_list[i], when you create a new tuple with size i, cpython will use the top object at free_list[i]
>>> t = ("aa", )
>>> t2 = ("aa", "bb")
>>> t3 = ("cc", "dd")
>>> t4 = ("ee", "ff")
>>> t5 = ("gg", "hh")
>>> del t2
>>> del t3
>>> del t4
>>> del t5