datarekha
Python Easy Asked at AmazonAsked at GoogleAsked at Microsoft

What is the difference between a list and a tuple, and when should you use each?

The short answer

Lists are mutable sequences; tuples are immutable. Use a tuple when the collection of items is fixed by meaning — coordinates, RGB values, function return values — and a list when the collection will grow, shrink, or be modified in place. Immutability also makes tuples hashable, so they can serve as dict keys or set members.

How to think about it

The surface answer — “lists are mutable, tuples are immutable” — is true and incomplete. A stronger answer says why that matters in practice: an immutable tuple is hashable, so it can be a dict key or set member; it’s slightly leaner in memory; and, just as importantly, it carries meaning — a tuple tells the next developer “these values belong together and won’t change,” which a list never promises.

The dividing line is mutability:

coords = (40.7128, -74.0060)    # tuple — a fixed (lat, lon) pair
coords[0] = 0.0                  # TypeError: 'tuple' object does not support item assignment

names = ["Alice", "Bob"]
names.append("Carol")            # fine — a list is meant to change

And because a tuple’s slots can’t be reassigned, Python can give it a stable hash — which is what lets it be a key where a list simply can’t:

grid = {}
grid[(0, 0)] = "origin"          # works — a tuple is hashable
grid[[0, 0]] = "origin"          # TypeError: unhashable type: 'list'

That single ability — tuple-as-key — quietly powers grid coordinates, composite cache keys, and multi-column lookups.

A worked example

import sys

# Tuples are a little leaner (lists over-allocate to make append cheap)
t = (1, 2, 3)
l = [1, 2, 3]
print(f"tuple size: {sys.getsizeof(t)} bytes")
print(f"list  size: {sys.getsizeof(l)} bytes")

# Hashable -> tuples make natural composite keys
locations = {
    (40.71, -74.00): "New York",
    (51.50,  -0.12): "London",
    (35.68, 139.69): "Tokyo",
}
print("NYC:", locations[(40.71, -74.00)])

# Tuples are the idiomatic "return several values" container
def bounding_box(points):
    xs = [p[0] for p in points]
    ys = [p[1] for p in points]
    return (min(xs), min(ys), max(xs), max(ys))

x_min, y_min, x_max, y_max = bounding_box([(1, 2), (5, 3), (0, 8)])
print(f"Bounding box: ({x_min},{y_min}) to ({x_max},{y_max})")

# The shallow-immutability gotcha
t2 = ([1, 2], 3)
t2[0].append(99)                 # the list INSIDE the tuple can still change
print("Mutated inner list:", t2)
try:
    hash(([1, 2], 3))            # ...so the tuple can't be hashed
except TypeError as e:
    print("Hash error:", e)
tuple size: 64 bytes
list  size: 120 bytes
NYC: New York
Bounding box: (0,2) to (5,8)
Mutated inner list: ([1, 2, 99], 3)
Hash error: unhashable type: 'list'

The sizes tell a small story: the list is nearly twice the tuple, because a list keeps spare capacity so that append is usually free, while a tuple — which will never grow — allocates exactly what it needs.

When to use which

SituationChoose
Fixed-meaning record (lat/lon, RGB, DB row)tuple
Returning several values from a functiontuple
A collection that grows or gets filteredlist
A stack, queue, or pipeline of itemslist
A dict key or set membertuple

For large numerical data, by the way, neither is the right tool — reach for a NumPy array.

Learn it properly Lists

Keep practising

All Python questions

Explore further

Skip to content