Table of Contents

    namedtuple

    PYTHON & DATA STRUCTURES

    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.

    In one line: A 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
    With namedtuple Fields get names, so the meaning is obvious and self-documenting.
    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)
    Remember You cannot do 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 _replace for "updates" since instances are immutable
    • Use _asdict() when you need JSON or dict output
    • Use defaults for optional trailing fields
    • Reach for a dataclass when you need mutability or methods

    Common Mistakes

    Bad Trying to mutate a field: p.x = 10 — raises AttributeError because namedtuples are immutable.
    Good Create a modified copy: p = p._replace(x=10).
    Bad Using invalid field names (keywords or duplicates) — raises a ValueError.
    Good Use 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.