30

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?

2
  • 2
    Don't you mean "linked list" instead every time you mention "list" in your question? Commented May 9, 2011 at 6:14
  • "I read here that array access is really slow in Python." - This was very out of date even when this question was originally asked. It's also talking about constant-factor overhead, while the question here is about big-O complexity. (Also, that source directly said - which was true in 2000, true in 2011, and true today - that list access is O(1); so it's hard to understand why the question was asked.) Commented Sep 8, 2023 at 6:02

4 Answers 4

47

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]

Sign up to request clarification or add additional context in comments.

2 Comments

+1 for giving a much better and much more detailed explanation!
"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)." can you point out a ressource that explains how the factor is actually determined ? Thanks in advance !
9

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.

Comments

2

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).

Comments

0

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."

2 Comments

For access, yes, you're right. Apologies :). I found stackoverflow.com/questions/68630/… which seems to suggest it depends on the operation in question.
That answer isn't very accurate, because it builds a constant list from scratch - which is what takes more time. This however isn't a common operation in real code. Once you have a list, there is no difference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.