Skip to content

Python · Data Structures

Python Tuples and Named Tuples Explained — Immutability, Packing, and namedtuple

4 min read Updated 2026-06-19 Share:

Practice Tuples & Named Tuples interview questions

Python tuples, explained

Tuples look like "immutable lists", but that framing misses the point. Tuples model fixed records — a related group of values with meaning by position — while lists model homogeneous collections. This guide covers the distinction, packing/unpacking, the depth of immutability, and named tuples.

Tuple vs list: it's about meaning

The technical difference is mutability, but the idiomatic difference is intent:

point = (3, 4)              # a record: (x, y) — fixed structure
scores = [88, 92, 79]      # a collection: any number of similar items

Use a tuple when position has meaning and the size is fixed (coordinates, a database row, a function returning multiple values). Use a list when you have a sequence of similar things you might add to or reorder.

Packing and unpacking

Creating a tuple is "packing"; pulling it apart is "unpacking". Parentheses are often optional:

p = 3, 4              # packing — p is (3, 4)
x, y = p             # unpacking
x, y = y, x          # swap with no temp variable

first, *rest = [1, 2, 3, 4]   # first=1, rest=[2, 3, 4] — star unpacking

The one gotcha: a single-element tuple needs a trailing comma, because the parentheses alone mean grouping:

(5)      # int 5
(5,)     # tuple (5,)

Tuples as return values

A function "returning multiple values" is really returning one tuple, which the caller unpacks:

def min_max(nums):
    return min(nums), max(nums)   # packs a tuple

lo, hi = min_max([3, 1, 7])       # unpacks it

Is immutability deep?

No — a tuple's immutability is shallow. You can't rebind which objects the tuple holds, but if one of those objects is mutable, it can still change:

t = (1, [2, 3])
t[1].append(4)       # OK — the list inside is mutable -> (1, [2, 3, 4])
t[1] = [9]           # TypeError — can't rebind a tuple slot

A consequence: a tuple is hashable only if all its elements are. (1, 2) is a valid dict key; (1, [2]) is not.

Why a tuple can be a dict key

Because an all-immutable tuple is hashable and its hash never changes, it can be a dictionary key or set element — a list cannot:

distances = {(0, 0): 0, (3, 4): 5}    # coordinates as keys — fine
{[0, 0]: 0}                           # TypeError: unhashable type: 'list'

namedtuple — fields with names

Plain tuples force you to remember what index means what. collections.namedtuple gives the fields names while staying a tuple (and still immutable, lightweight, and unpackable):

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
p.x, p.y          # 3, 4 — readable access
p[0]              # 3    — still indexable like a tuple
x, y = p          # still unpackable
p._replace(x=10)  # Point(x=10, y=4) — returns a new tuple

typing.NamedTuple — the typed, class-based form

For type hints and a cleaner class syntax, use typing.NamedTuple:

from typing import NamedTuple

class Point(NamedTuple):
    x: int
    y: int
    def distance(self) -> float:
        return (self.x ** 2 + self.y ** 2) ** 0.5

Point(3, 4).distance()   # 5.0

When you need mutability or lots of behaviour, reach for a @dataclass instead; for a small immutable record, a named tuple is perfect.

Recap

Tuples model fixed records; lists model collections — that intent matters more than "immutable list". Pack with commas, unpack with assignment (and remember the trailing comma for one-element tuples). Immutability is shallow: a tuple can contain a mutable list, and a tuple is hashable (usable as a dict key) only when all its elements are. Reach for collections.namedtuple or typing.NamedTuple to name the fields without giving up tuple-ness.

More ways to practice

The self-quiz is live. Get notified when mock interviews and new question packs drop.

or
Join our WhatsApp Channel