Dataslope logoDataslope

Lists

Python's general-purpose ordered, mutable sequence

A list is Python's workhorse collection: an ordered, mutable sequence that can hold values of any type. Lists are everywhere in real-world Python — search results from an API, user records from a database, file paths for batch processing, task queues, log messages, and more. If you need to store multiple things and might change them later, a list is usually your first choice.

Every snippet on this page runs in your browser — no setup required.

Creating a list

The simplest list is written with square brackets, separating items with commas.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Lists are heterogeneous: they can mix types freely.

Code Block
Python 3.13.2

The list() constructor converts any iterable into a list.

Code Block
Python 3.13.2

How lists work under the hood

Lists are implemented as dynamic arrays: a contiguous block of memory holding references to objects. This gives O(1) random access by index but O(n) insertion/deletion in the middle. Think of a list as a row of numbered parking spots, where each spot points to the actual object.

Lists in the wild

Every web framework returns search results as a list. Every database driver gives you rows as a list. Every file system walk yields paths in a list. Lists are the default sequence type in Python, and understanding them deeply pays off constantly.

Indexing

Lists support zero-based indexing. Negative indices count from the end.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Out-of-range access raises an IndexError.

Code Block
Python 3.13.2

Slicing

Slices let you extract a sublist with [start:stop:step]. The stop index is exclusive.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

The step parameter lets you skip items or reverse.

Code Block
Python 3.13.2

Mutation via assignment

Unlike strings (which are immutable), you can assign directly through an index or slice.

Code Block
Python 3.13.2

Slice assignment can change the list's length.

Code Block
Python 3.13.2

Slice assignment replaces, not item-by-item

When you write xs[1:4] = [9], Python removes indices 1 through 3 and inserts the single item 9. The lengths do not need to match. This trips up newcomers who expect element-by-element replacement.

Common methods: adding items

The three main ways to grow a list:

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

append and extend are O(1) amortized, so they are fast. insert at the front or middle is O(n) because it shifts all subsequent elements.

Common methods: removing items

Code Block
Python 3.13.2

remove deletes the first occurrence and raises ValueError if the item is missing.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

Common methods: searching and counting

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Sorting and reversing

sort() and reverse() modify the list in place and return None.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

For case-insensitive string sorting, pass a key function.

Code Block
Python 3.13.2

If you want a new sorted list without modifying the original, use the built-in sorted().

Code Block
Python 3.13.2

Iteration

The for loop is the canonical way to visit each item.

Code Block
Python 3.13.2

When you also need the index, use enumerate.

Code Block
Python 3.13.2

To iterate two lists in parallel, use zip.

Code Block
Python 3.13.2

Membership and aggregates

Code Block
Python 3.13.2

Membership testing is O(n)

item in list scans the entire list in the worst case. If you are doing frequent membership checks, consider converting to a set, where in is O(1).

Code Block
Python 3.13.2

Copying lists: shallow vs deep

Assignment does not copy. Both names point to the same list.

Code Block
Python 3.13.2

Use .copy() or slicing [:] for a shallow copy.

Code Block
Python 3.13.2

Shallow means nested structures are still shared.

Code Block
Python 3.13.2

For true independence, use copy.deepcopy.

Code Block
Python 3.13.2

Modifying while iterating

Changing a list's length during iteration invalidates the iterator and leads to skipped items or infinite loops. If you must remove items, iterate over a copy: for x in xs[:] or build a new list with a comprehension.

Stacks and queues

Lists make excellent stacks because append and pop at the end are both O(1).

Code Block
Python 3.13.2

For queues (FIFO), prefer collections.deque, which supports O(1) operations at both ends. Using a list as a queue means O(n) pop(0) every time you dequeue.

Code Block
Python 3.13.2

Challenges

Challenge
Python 3.13.2
Rotate a list

Define a function rotate(items, n) that returns a new list with the items rotated left by n positions. For example, rotate([1, 2, 3, 4, 5], 2) returns [3, 4, 5, 1, 2].

Hint: slicing makes this one-liner.

Challenge
Python 3.13.2
Remove duplicates, preserving order

Define dedupe(items) that returns a list of the items in items with duplicates removed, keeping the first occurrence of each. For example, dedupe([3, 1, 3, 2, 1, 4]) returns [3, 1, 2, 4].

Hint: a set of "already seen" items is a great fit.

Challenge
Python 3.13.2
Flatten a nested list

Define a function flatten(nested) that takes a list of lists and returns a single flat list. For example, flatten([[1, 2], [3], [4, 5]]) returns [1, 2, 3, 4, 5].

You may assume the list is only one level deep.

QuestionSelect one

What is the value of xs after this code runs?

xs = [1, 2, 3, 4, 5]
xs[1:4] = [9]

[1, 9, 4, 5]

[1, 9, 5]

[1, 9, 2, 3, 4, 5]

A ValueError because lengths differ

QuestionSelect one

Which operation modifies the list in place?

sorted(xs)

xs.sort()

xs + [9]

list(xs)

QuestionSelect one

What does xs.pop() return if xs = [1, 2, 3]?

[1, 2]

1

3

None

QuestionSelect one

What is the time complexity of item in xs where xs is a list?

O(1)

O(n)

O(log n)

O(n²)

Lists are mutable. Their immutable cousin, the tuple, is next.

On this page