Working with Python Lists

Learn what a Python list is, how it stores ordered mutable data, and why lists are the most commonly used collection type in Python programs.

5 min read

A Python list is the collection type you will use more than any other in day-to-day programming. It holds items in a specific order, lets you change those items whenever you need to, and grows or shrinks automatically as you add or remove elements. If you have worked through the earlier sections on strings and data types, you already understand zero-based indexing and the idea of a sequence. A list extends those ideas into a container that you can reshape at runtime, which is why lists are the backbone of so many Python programs. This article introduces lists and explains how they work so you can start using them with confidence. If you want the big-picture comparison of all four collection types, start with Python collections explained.

At its core, a list is an ordered sequence of object references stored in a contiguous block of memory. Python manages the memory for you, so you never need to declare a maximum size or worry about overflowing a fixed buffer. You can start with an empty list, append a thousand items inside a loop, remove half of them later, and Python handles the resizing behind the scenes. This dynamic nature makes lists the right default choice when you are not sure which collection type to use. If your data has an order and might change, a list fits.

How lists work under the hood

When you create a list, Python allocates an array of pointers in memory. Each pointer refers to a Python object stored elsewhere on the heap. The list itself does not contain the objects; it contains references to them. This is why a single list can hold integers, strings, other lists, and custom objects all at once. Each slot is just a pointer, and Python does not enforce any type restriction on what that pointer points to.

The internal array is overallocated, meaning Python reserves more slots than the current number of items. When you append to a list, Python places the new reference in the next available slot. If all reserved slots are full, Python allocates a new, larger array, copies the existing references into it, and frees the old array. This overallocation strategy makes repeated appends efficient. Instead of resizing on every append, Python grows the array by a proportional amount each time it runs out of room, so the average cost per append stays low even as the list grows into the thousands or millions of items.

Removing items from the end of a list is fast because Python just clears the last pointer slot and decrements the size counter. Removing items from the beginning or middle is slower because all the subsequent pointers must shift left to fill the gap. This performance characteristic is worth keeping in mind. If your program frequently adds and removes items at both ends, the deque type from the collections module in the standard library is a better choice than a plain list.

Creating lists and reading their contents

You create a list by writing a comma-separated sequence of values inside square brackets. The empty list is simply a pair of brackets with nothing between them. A list of numbers contains numeric values separated by commas, and a list of strings contains quoted text values separated by commas. You can also call the list constructor on any iterable to turn it into a list.

pythonpython
empty = []
numbers = [10, 20, 30, 40]
mixed = [1, "hello", 3.14, True]
from_range = list(range(5))

Each item in a list has a numeric position called its index, and Python indexes start at zero. The first item is at index 0, the second at index 1, and so on. Negative indices count backward from the end, so the index for the last item is always -1 regardless of the list's length. Trying to access an index that does not exist raises an IndexError. Lists also support slicing with the colon operator, which extracts a new list containing a range of items. The article on creating and accessing Python lists covers indexing and slicing in full detail.

Why lists are mutable and why that matters

Mutability means you can change a list after it is created without creating a new list object. You can replace an item at a specific index by assigning to it, add items to the end, insert items at a chosen position, and delete items by index or by value. Each of these operations modifies the list in place, and none of them return a new list. This is why methods like append and remove return None. They signal that they have changed the original rather than producing a copy.

This in-place modification is powerful but requires care. When you assign a list to a new variable with the equals sign, you are not creating a copy. You are creating a second name that points to the same list object. If you modify the list through either name, the change is visible through both. This aliasing behavior is a common source of bugs for beginners, and the article on copying Python lists later in this section explains how to make independent copies when you need them.

Mutability also means lists cannot be used as dictionary keys or as elements of a set. Both dictionaries and sets require their keys and elements to be hashable, and a mutable object cannot have a stable hash value because its contents can change. If you need a list-like object that can serve as a dictionary key, convert it to a tuple first.

When to choose a list over other collections

Lists are the right choice when your data has a meaningful order and that order needs to be preserved, when you expect to add or remove items over the lifetime of the program, or when you need to sort or reverse the collection. A timeline of events belongs in a list because the sequence matters. A queue of pending tasks belongs in a list because items arrive and depart. A collection of search results belongs in a list because you want to display them in ranked order.

If your data does not need an order and you care primarily about uniqueness, reach for a set instead. If your data is a fixed grouping that should never change, a tuple communicates that intent and provides the safety of immutability. If your data is a set of key-value associations where you need fast lookups by a known identifier, a dictionary is the natural fit. The overview article on Python collections compares all four types side by side.

The next several articles in this section build your list skills step by step. You will learn how to create lists through every available syntax, how to access individual items and slices by index, how to modify lists by adding, removing, and rearranging elements, and how to sort and reverse lists for ordered output.

Rune AI

Rune AI

Key Insights

  • A Python list is an ordered, mutable sequence that can hold items of any type.
  • Lists are created with square brackets and items are accessed by zero-based index.
  • Lists grow and shrink dynamically; you can append, insert, remove, and pop items at will.
  • The rich set of list methods covers nearly every common data manipulation need.
  • Mutability means list modifications happen in place, which is powerful but requires care with aliasing.
RunePowered by Rune AI

Frequently Asked Questions

What is a Python list?

A Python list is a built-in mutable sequence type that stores an ordered collection of items. Items in a list can be of any type, and a single list can hold integers, strings, other lists, and custom objects simultaneously. Lists are created with square brackets and support indexing, slicing, appending, inserting, removing, sorting, and reversal.

Can a Python list hold different data types?

Yes. A single Python list can contain a mix of integers, floats, strings, booleans, other lists, tuples, dictionaries, and instances of any Python class. While mixing types is allowed, most production code keeps list elements the same type for predictability when iterating and processing.

How is a list different from an array in other languages?

Python lists are dynamic and heterogeneous, meaning they grow and shrink automatically and can hold any type of element. Arrays in languages like Java or C have a fixed size and a single declared element type. Python's array module and NumPy arrays provide fixed-type, memory-efficient alternatives when performance is critical.

Conclusion

Python lists are the first collection type you reach for when order matters and the data might change. Their combination of indexing, slicing, dynamic resizing, and a rich set of built-in methods makes them suitable for a wider range of tasks than any other collection type.