Python 列表、访问和调整运行时大小的内部结构

发布于 2024-11-06 00:53:47 字数 340 浏览 7 评论 0原文

Python 的 [] 是列表还是数组?
索引的访问时间是像数组一样 O(1) 还是像列表一样 O(n) ?
追加/调整大小是像列表一样 O(1) 还是像数组一样 O(n) ,还是可以管理 O(1) 访问和调整大小的混合体?

在这里读到,Python 中的数组访问非常慢。然而,当我使用字典(Python 的字典应该非常快)和列表编写递归斐波那契过程的记忆版本时,它们的时间相等。这是为什么呢?

Python 元组的访问时间是否比 Python 列表更快?

Is Python's [] a list or an array?
Is the access time of an index O(1) like an array or O(n) like a list?
Is appending/resizing O(1) like a list or O(n) like an array, or is it a hybrid that can manage O(1) for accessing and resizing?

I read here that array access is really slow in Python. However, when I wrote a memoized version of a recursive fibonacci procedure using both a dictionary (Python's dictionary is suppose to be really fast) and a list, they had equal times. Why is this?

Does a Python tuple have faster access times than a python list?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

十二 2024-11-13 00:53:48

Python 的[] 是作为数组 实现的,而不是链表。尽管调整大小的时间复杂度为 O(n),但追加其大小的时间复杂度为 O(1),因为调整大小的情况很少发生。如果您不熟悉其工作原理,请阅读有关动态数组的维基百科条目。 Python 的列表不会每次扩展 2 倍,它比这要复杂一点,但扩展仍然旨在使追加摊销 O(1)。

然而,在中间插入总是低效的 O(n),因为可能需要移动 n 个项目。

元组并不比列表快——它们只是底层的不可变列表(*)。

关于您的字典测试:根据您的具体实现,列表中的缓存将比字典中的缓存更快。然而,Python 的字典是高度优化的,特别是对于少量的键来说,效果会很好。


(*) 这是 Python 2.6 中列表的“获取项目”C 函数:

PyObject *
PyList_GetItem(PyObject *op, Py_ssize_t i)
{
    if (!PyList_Check(op)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    if (i < 0 || i >= Py_SIZE(op)) {
        if (indexerr == NULL)
            indexerr = PyString_FromString(
                "list index out of range");
        PyErr_SetObject(PyExc_IndexError, indexerr);
        return NULL;
    }
    return ((PyListObject *)op) -> ob_item[i];
}

这是一个元组的:

PyObject *
PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)
{
    if (!PyTuple_Check(op)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    if (i < 0 || i >= Py_SIZE(op)) {
        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
        return NULL;
    }
    return ((PyTupleObject *)op) -> ob_item[i];
}

如您所见,它们几乎完全相同。最后,经过一些类型和边界检查,这是一个带有索引的简单指针访问。

[参考:有关数据类型操作时间复杂度的 Python 文档]

Python's [] is implemented as an array, not a linked list. Although resizing is O(n), appending to it is amortized O(1), because resizes happen very rarely. If you're not familiar with how this works, read this Wikipedia entry on dynamic arrays. Python's list doesn't expand by a factor of 2 each time, it's a bit more complicated than that, but the expansions are still designed to make appending amortized O(1).

Inserting in the middle, however, is always an inefficient O(n), because n items may have to be moved.

Tuples aren't faster than lists - they're just immutable lists under the hood (*).

Regarding your dictionary test: depending on your exact implementation, caching in a list will be faster than with a dict. However, Python's dicts are highly optimized, and especially for small amounts of keys will perform great.


(*) Here's a list's "get item" C function in Python 2.6:

PyObject *
PyList_GetItem(PyObject *op, Py_ssize_t i)
{
    if (!PyList_Check(op)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    if (i < 0 || i >= Py_SIZE(op)) {
        if (indexerr == NULL)
            indexerr = PyString_FromString(
                "list index out of range");
        PyErr_SetObject(PyExc_IndexError, indexerr);
        return NULL;
    }
    return ((PyListObject *)op) -> ob_item[i];
}

And this is a tuple's:

PyObject *
PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)
{
    if (!PyTuple_Check(op)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    if (i < 0 || i >= Py_SIZE(op)) {
        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
        return NULL;
    }
    return ((PyTupleObject *)op) -> ob_item[i];
}

As you can see, they're almost exactly the same. In the end, after some type and bound checking, it's a simple pointer access with an index.

[Reference: Python documentation on Time Complexity for data type operations]

友欢 2024-11-13 00:53:48

此处有一个很棒的列表,概述了 Python 数据类型的时间复杂度。在您的情况下,项目检索应该是 O(1) 时间。

There is a great list here outlining the time complexity of the python data types. In your case item retrieval should be O(1) time.

唯憾梦倾城 2024-11-13 00:53:48

Python的列表相当于Java的ArrayList。从列表和元组中获取项目的访问时间应该O(1)< /代码>。 Norvig 的文章指出,Python 的列表相当于 Java 中的 Vector 或 Lisp 中的可调整数组,确实需要更多空间,但访问时间为 O(1)

Python's list is comparable to ArrayList of Java. The access time for getting an item from both list and tuple should O(1). Norvig's article points out that Python's list is comparable to Vector in Java or Adjustable Array in Lisp and you really need more space, but the access time is O(1).

予囚 2024-11-13 00:53:48

元组比列表更快。我不知道底层的实现。我在《Dive into Python》中读到过这一点:)相关摘录:

“元组比列表更快。如果您定义一组常量值,并且您要做的就是迭代它,使用元组而不是列表。”

Tuples are faster than lists. I don't know the underlying implementation. I read that in 'Dive into Python' at some point :) The relevant excerpt:

"Tuples are faster than lists. If you're defining a constant set of values and all you're ever going to do with it is iterate through it, use a tuple instead of a list."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文