From the Official Documentation
Python’s lists are really variable-length arrays, not Lisp-style linked lists. The implementation uses a contiguous array of references to other objects, and keeps a pointer to this array and the array’s length in a list head structure.
This makes indexing a list a[i] an operation whose cost is independent of the size of the list or the value of the index.
When items are appended or inserted, the array of references is resized. Some cleverness is applied to improve the performance of appending items repeatedly; when the array must be grown, some extra space is allocated so the next few times don’t require an actual resize.
So, python lists are nothing but variable length arrays. I dug into source code of cpython, and on expanding the macro, the basic structure is defined as:
typedef struct {
PyObject_VAR_HEAD
PyObject **ob_item;
Py_ssize_t allocated;
} PyListObject;
Coming to the reason why they chose a Doubly Linked List:
• Skip Back/Forward- Because each node in a double linked list has a pointer the previous and next node, it is easy to implement skip forward/backward functionality.
• Play Next Track- The pointer to the next node also makes it quite easy to start the next track when a track is over.
• Append When you add a new track to a playlist, you tack it on to the end. In a linked list, adding a new element is constant time — O(1) operation. Note that as the songs are read in from a data source and added to the play list, this will be done as a sequence of calls to append.
• Beginning/End- Finally, because a linked list has head and tail properties, this provides for an easy way to delineate the beginning and end of a playlist