What is a namedtuple in Python and when should I use one?
Short answer
A namedtuple is a lightweight immutable record whose fields have names, so you access them by attribute instead of position. Use it for small fixed records where a full class would be overkill.
The short version
A namedtuple is a tuple whose positions also have names, so you can read point.x instead of point[0]. It is immutable and memory-light, making it ideal for small fixed records where a full class would be more than you need. For anything with behaviour or that needs defaults and type hints, a dataclass is often a better fit.
Defining and using one
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(1, 2)
print(p.x, p.y) # 1 2
print(p) # Point(x=1, y=2)
The named access makes code far more readable than positional indexing, and the automatic repr (Point(x=1, y=2)) is helpful when debugging.
The problem it solves
A plain tuple works but is cryptic, because the meaning of each position is not visible at the point of use.
p = (1, 2)
print(p[0], p[1]) # what are 0 and 1 supposed to be?
Six months later, p[0] gives no clue that it is the x coordinate. namedtuple puts the names in the code, so the intent is clear.
It is still a tuple
A namedtuple is a real tuple, so it unpacks, indexes and iterates like one, which keeps it compatible with code that expects tuples.
x, y = p # unpacking works
p[0] # positional access still works
Immutability
Like any tuple, a namedtuple cannot be changed after creation, so it is safe to use as a dictionary key or share without fear of mutation.
p.x = 9 # AttributeError, cannot assign
To make a modified copy, use _replace, which returns a new namedtuple.
p2 = p._replace(x=9) # Point(x=9, y=2), p unchanged
Useful helpers
_asdict converts to a dictionary, and _fields lists the field names, both handy for serialisation and introspection.
p._asdict() # {'x': 1, 'y': 2}
Point._fields # ('x', 'y')
namedtuple versus dataclass
Choose a namedtuple for a small, immutable record that should behave like a tuple. Choose a dataclass when you want mutability, default values, type annotations, or methods. A modern alternative, typing.NamedTuple, adds type hints and a class-based syntax to the namedtuple idea, which many people now prefer for clarity.
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int = 0
This gives the same immutable record with annotations and a default, combining the lightness of a namedtuple with clearer definitions.