list vs tuple

RoadmapsPython Backend

Overview

A tuple is an ordered, immutable sequence. You create one with parentheses or just commas — the commas are what actually make the tuple, not the parentheses: coords = (40.7128, -74.0060) same = 40.7128, -74.0060 A single-element tuple REQUIRES a trailing comma — without it Python sees plain parentheses: one = (42,) # tuple with one int not_a_tuple = (42) # just the int 42 Because tuples are immutable, you cannot append, remove, or reassign an element after creation. But immutability makes tuples hashable (as long as every element inside is also hashable), so they can serve as dict keys or set members: cache = {} cache[('users', 'page', 2)] = [{'id': 7}, {'id': 8}] Tuple unpacking lets you extract elements into named variables in one step: status, body = (200, {'ok': True}) This is why functions that return multiple values actually return a tuple — `return status, body` packs them, and the caller unpacks. Think of a tuple as a sealed envelope: once you put items inside and close it, you can read the contents but cannot swap, add, or remove anything. That seal is what makes it safe to use as a dict key.

Tuples give you a lightweight, read-only container for fixed-size data: coordinates, status-and-body pairs, composite cache keys. Their immutability guarantees the data will not change by accident, and their hashability lets you use multi-part keys in dicts and sets — something a list cannot do.

Where used: FastAPI returning (status, body) pairs, Database row results from cursor.fetchall(), Composite dict keys for caching and lookups

Why learn this

Code walkthrough

row = ('srv-1', 8080, 'healthy')
host, port, status = row
print(host)
print(port)
print(status)
print(type(row))

Focus: Unpacking assigns each tuple element to a named variable in one step — host, port, status each get their value from the corresponding position in row.

Aha moment

a = (1, 2, [3, 4])
a[2].append(5)
print(a)

Prediction: Tuples are immutable. What happens when you try to mutate the list inside the tuple?

Common guess: TypeError — you cannot change a tuple

The tuple is immutable: you cannot reassign a[2] to a different object. But the list AT a[2] is still a mutable object — you can change its contents. Immutability freezes the references in the tuple, not the objects those references point to.

Common mistakes

Glossary

hashable
An object that has a fixed value that never changes during its lifetime, allowing it to be used as a dictionary key or set item. Example: `cache[('users', 1)] = data`.
unpacking
Extracting multiple items from a collection, like a tuple or list, and assigning them to separate variables all at once. Example: `host, port = ('localhost', 8080)`.

Recall questions

Understanding checks

What will this code print?

<class 'int'>

Without a trailing comma, `(42)` is just the integer 42 wrapped in parentheses. You need `(42,)` to create a tuple.

Why can a tuple be used as a dictionary key, but a list cannot?

Because tuples are immutable and hashable (as long as all their contents are hashable), whereas lists are mutable.

Dictionary keys must be hashable, which requires them to remain unmodified throughout their lifetime.

Practice tasks

Composite cache key

The get_cached function currently uses a string key for caching. Modify its behavior to use a tuple of (tenant, resource, page) as the dictionary key instead, which is safer and faster.

Challenge

Build a request-rate counter by endpoint

Write count_requests(logs) where logs is a list of (method, path) tuples like [('GET', '/users'), ('POST', '/users'), ('GET', '/users')]. Return a dict mapping each (method, path) tuple to its count. Print the result for a sample log list.

Continue learning

Previous: Mutable vs immutable types

Previous: Slicing

Return to Python Backend Roadmap