列表和元组的内部实现
列表
Python 3.7 的 list 源码:
listobject.h:
https://github.com/python/cpython/blob/949fe976d5c62ae63ed505ecf729f815d0baccfc/Include/listobject.h#L23
listobject.c:
https://github.com/python/cpython/blob/3d75bd15ac82575967db367c517d7e6e703a6de3/Objects/listobject.c#L33
list 的具体结构如下:
#ifndef Py_LIMITED_API
typedef struct {
PyObject_VAR_HEAD
/* Vector of pointers to list elements. list[0] is ob_item[0], etc. */
PyObject **ob_item;
/* ob_item contains space for 'allocated' elements. The number
* currently in use is ob_size.
* Invariants:
* 0 <= ob_size <= allocated
* len(list) == ob_size
* ob_item == NULL implies ob_size == allocated == 0
* list.sort() temporarily sets allocated to -1 to detect mutations.
*
* Items must normally not be NULL, except during construction when
* the list is not yet visible outside the function that builds it.
*/
Py_ssize_t allocated;
} PyListObject;
#endif
list 本质上是一个过度分配的 array。其中, ob_item 是一个指针列表,里面的每个指针都指向列表的元素。而allocated 则存储了这个列表已经被分配的空间大小。
可以看到源码注释中 ob_item contains space for 'allocated' elements. The number currently in use is ob_size. 那么 allocated 与列表实际空间大小是有区别。列表实际空间大小, 是指 len(list) 返回的结果,也就是源码注释中ob_size, 表示这个列表总共存储了多少个元素。
实际情况下, 为了优化存储结构, 避免每次增加元素都要重新分配内存, 列表预分配的空间 allocated 往往会大于ob_size,所以它们的关系如同注释所示 len(list) == ob_size<= allocated。如果当前列表分配的空间已满(即 allocated == len(list)) , 则会向系统请求更大的内存空间, 并把原来的元素全部拷⻉过去。
元组
Python 3.7 的 tuple 源码:
tupleobject.h:
https://github.com/python/cpython/blob/3d75bd15ac82575967db367c517d7e6e703a6de3/Include/tupleobject.h#L25
tupleobject.c:
https://github.com/python/cpython/blob/3d75bd15ac82575967db367c517d7e6e703a6de3/Objects/tupleobject.c#L16
tuple 的具体结构如下:
#ifndef Py_LIMITED_API
typedef struct {
PyObject_VAR_HEAD
PyObject *ob_item[1];
/* ob_item contains space for 'ob_size' elements.
* Items must normally not be NULL, except during construction when
* the tuple is not yet visible outside the function that builds it.
*/
} PyTupleObject;
#endif
注意注释的说明,其空间大小固定它依然也是一个array
参考资料:
极客时间 Python核心技术与实战学习
Python核心技术与实战(极客时间)链接:
http://gk.link/a/103Sv
个人Blog:
https://lichangke.github.io/
欢迎大家来一起交流学习