namedtuple
Python namedtuple — The Complete Guide
Master collections.namedtuple to create lightweight, immutable, self-documenting records with named fields instead of cryptic indexes.
Introduction
namedtuple is a factory function from Python's built-in collections module that creates a tuple
subclass with named fields. It gives you all the benefits of a regular tuple — immutability, low memory, fast access — while
letting you refer to elements by descriptive names (like point.x) instead of forgettable numeric indexes (like
point[0]). The result is cleaner, self-documenting code that reads like a lightweight class but stays as efficient as a tuple.
namedtuple is a tuple whose fields have names — readable like a class, lightweight like a tuple.
Real-World Analogy
The Labelled ID Card
A plain tuple is like a strip of unlabelled data — you must remember that position 0 is the name and position 2 is the age. A namedtuple is an ID card with printed labels: "Name", "Age", "City". The information is the same, but now it's instantly readable and hard to misuse.
Prerequisites
Before You Start
- Python 3.x installed
- Understanding of tuples and tuple unpacking
- The factory is built in — just
from collections import namedtuple - Familiarity with the concept of immutability
- Basic knowledge of classes (helpful for comparison)
The Problem It Solves
Plain tuples force you to remember what each index means, which is error-prone.
# Plain tuple — what does each index mean?
point = (3, 4)
print(point[0]) # 3 (is this x or y? unclear)
print(point[1]) # 4
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x) # 3 — clear!
print(p.y) # 4
print(p) # Point(x=3, y=4)
Ways to Define Fields
The field names can be given as a list, a space-separated string, or a comma-separated string.
from collections import namedtuple
# All three are equivalent:
Point = namedtuple("Point", ["x", "y"])
Point = namedtuple("Point", "x y")
Point = namedtuple("Point", "x, y")
p = Point(10, 20)
print(p) # Point(x=10, y=20)
Accessing Values
You can access fields by name or by index, and unpack like any tuple.
from collections import namedtuple
Person = namedtuple("Person", "name age city")
p = Person("Rumman", 30, "Kolkata")
# By name
print(p.name) # Rumman
# By index (still a tuple!)
print(p[1]) # 30
# Unpacking works
name, age, city = p
print(name, age, city) # Rumman 30 Kolkata
Special Methods & Attributes
| Method / Attribute | Purpose |
|---|---|
_make(iterable) |
Create a new instance from an iterable |
_asdict() |
Return the fields as a dictionary |
_replace(**kwargs) |
Return a new instance with some fields changed |
_fields |
Tuple of field names |
_field_defaults |
Dict of default values for fields |
Building from an Iterable with _make
from collections import namedtuple
Point = namedtuple("Point", "x y")
data = [7, 8]
p = Point._make(data) # build from a list/iterable
print(p) # Point(x=7, y=8)
Converting to a Dictionary with _asdict
from collections import namedtuple
Person = namedtuple("Person", "name age")
p = Person("Alice", 25)
print(p._asdict()) # {'name': 'Alice', 'age': 25}
Immutable Updates with _replace
Namedtuples are immutable — _replace returns a new instance instead of mutating the original.
from collections import namedtuple
Point = namedtuple("Point", "x y")
p = Point(1, 2)
p2 = p._replace(y=99) # creates a new tuple
print(p) # Point(x=1, y=2) — original unchanged
print(p2) # Point(x=1, y=99)
p.x = 5 — namedtuples are immutable and will raise an AttributeError.
Default Values
Use the defaults parameter (Python 3.7+) to give trailing fields default values.
from collections import namedtuple
# Defaults apply to the rightmost fields
Account = namedtuple("Account", "owner balance currency", defaults=[0, "USD"])
a = Account("Rumman")
print(a) # Account(owner='Rumman', balance=0, currency='USD')
b = Account("Alice", 500)
print(b) # Account(owner='Alice', balance=500, currency='USD')
namedtuple vs Alternatives
| Feature | namedtuple | dict | dataclass |
|---|---|---|---|
| Immutable | Yes | No | Optional (frozen=True) |
| Named access | Yes | Yes (by key) | Yes |
| Index access | Yes | No | No |
| Memory | Very low | Higher | Higher |
| Iterable/unpackable | Yes | Keys only | Not by default |
Memory Efficiency
Because a namedtuple stores no per-instance __dict__, its memory footprint is essentially that of a plain tuple —
far smaller than a dict holding the same \(k\) fields:
\[ \text{Mem}_{\text{namedtuple}} \approx \text{Mem}_{\text{tuple}} \; \ll \; \text{Mem}_{\text{dict}} \]
For millions of small records, this difference in per-object overhead adds up to significant memory savings.
Real Example: Returning Multiple Values
Namedtuples make functions that return several values self-explanatory.
from collections import namedtuple
Stats = namedtuple("Stats", "minimum maximum average")
def analyze(numbers):
return Stats(min(numbers), max(numbers), sum(numbers) / len(numbers))
result = analyze([4, 8, 15, 16, 23])
print(result.minimum) # 4
print(result.average) # 13.2
print(result) # Stats(minimum=4, maximum=23, average=13.2)
Best Practices
Do This
- Use namedtuples for small, immutable records instead of raw tuples
- Use them to return multiple named values from a function
- Use
_replacefor "updates" since instances are immutable - Use
_asdict()when you need JSON or dict output - Use
defaultsfor optional trailing fields - Reach for a
dataclasswhen you need mutability or methods
Common Mistakes
p.x = 10 — raises AttributeError because namedtuples are immutable.
p = p._replace(x=10).
rename=True to auto-fix invalid field names to positional ones.
Interview Questions
| Question | Short Answer |
|---|---|
| What is a namedtuple? | A tuple subclass with named fields for readable, self-documenting records. |
| Is a namedtuple mutable? | No — it's immutable like a regular tuple. |
| How do you "update" a field? | Use _replace(), which returns a new instance. |
| How to convert to a dict? | Call _asdict(). |
| namedtuple vs dataclass? | namedtuple is immutable and tuple-like; dataclass is mutable and class-like. |
Quick Revision
| Goal | Code |
|---|---|
| Define | namedtuple("P", "x y") |
| Create | P(1, 2) |
| From iterable | P._make([1, 2]) |
| To dict | p._asdict() |
| Copy with change | p._replace(x=9) |
Key Takeaways
namedtuple gives you named, self-documenting records that are immutable and
memory-efficient like tuples. Access fields by name or index, "update" with _replace,
convert with _asdict — and switch to a dataclass when you need mutability or behaviour.