Python列表的基础数据结构是什么?


72

用于实现Python内置列表数据类型的典型底层数据结构是什么?


两种选择:1)出于好奇,或2)过早优化。
flybywire

1
有人问我这个问题,我告诉他们我的直觉是实现是基于数组的,但是我不确定。这引起了我的好奇心,所以我决定问一下。
Nixuz

14
信不信由你,我确实花了几分钟的时间来寻找答案,即使我已经下载了源代码,我也可能不知道从哪里开始。我以为这里的人会花最少的努力就能知道答案,看来我是对的。轻松代表他们,快速回答我,每个人都赢。
Nixuz

17
这一点都不傻。Python列表中包含append()操作而不包含prepend()操作的全部原因正是Guido等人。认为列表用户需要非常明确地意识到以下事实:在数组中添加内容既简单又高效,而在其前面添加内容则非常昂贵。
布兰登·罗兹

Answers:


54

列表对象被实现为数组。它们针对快速的固定长度操作进行了优化,并为pop(0)和insert(0,v)操作产生O(n)内存移动成本,这些操作会同时更改基础数据表示的大小和位置。

另请参阅:http : //docs.python.org/library/collections.html#collections.deque

顺便说一句,我发现有趣的是,有关数据结构的Python教程建议使用pop(0)模拟队列,但不提及O(n)或双端队列选项。

http://docs.python.org/tutorial/datastructures.html#using-lists-as-queues


6
该教程早于双端队列模块就存在了,这就是为什么。如果可能的话,将其报告给bugs.python.org并附上正确句子的补丁,本教程将不再给出错误的提示。
菲利普·F

在几次采访中,我被告知列表的底层数据结构是链接列表。那是对的吗?在这种情况下,对于字典来说,它也是链表。是这样吗?
Shruti Kar

27

CPython:

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;

从下一行可以看出,列表被声明为的指针数组PyObjects

PyObject **ob_item;


0

尽管很明显,但值得一提的是Python列表是Dynamic数组(与Static数组相对)。这是面试问题/学术不足中的一个重要区别。

由于数组是动态的,因此Python在声明时会保留大量内存,例如:

somelist = []

由于已经预留了额外的内存somelist.append(),因此O(1)大多数情况下仅执行写入下一个保留的内存插槽。对于静态数组,通常数组已满(即,如果有4个字节,则数组大小为4),并且附加总是会出现,O(n)因为它们需要保留一组全新的内存(现在可能是5个字节)并复制内容。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.