Named tuple and default values for optional keyword arguments
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python's namedtuple from the collections module creates lightweight, immutable tuple subclasses with named fields. Adding default values for optional fields requires specific techniques because namedtuple does not natively support defaults in Python versions before 3.6.1. Since Python 3.6.1, namedtuple accepts a defaults parameter. For more flexibility, typing.NamedTuple and dataclasses provide cleaner syntax for defaults. This article covers all approaches.
Basic NamedTuple
Without defaults, all fields are required. Point() or Point(1) raises TypeError.
Defaults with defaults Parameter (Python 3.6.1+)
defaults applies from right to left. If there are 4 fields and 2 defaults, the last 2 fields get defaults while the first 2 remain required.
Using typing.NamedTuple (Python 3.6+)
Class-based syntax with type hints and defaults:
Fields without defaults must come before fields with defaults, just like function arguments.
Pre-3.6 Workaround: __new__.__defaults__
This sets default values by modifying the __defaults__ tuple on the __new__ method. It works in Python 2 and early Python 3.
Using _replace for Updating
Since namedtuples are immutable, use _replace to create modified copies:
Comparison with Dataclasses
| Feature | namedtuple | typing.NamedTuple | dataclass |
| Immutable | Yes | Yes | No (unless frozen=True) |
| Defaults | Yes (3.6.1+) | Yes | Yes |
| Type hints | No | Yes | Yes |
| Tuple unpacking | Yes | Yes | No |
_replace method | Yes | Yes | No (use replace() 3.13+) |
| Custom methods | No | Limited | Yes |
| Memory efficiency | Best | Best | Good |
Converting Between Formats
Common Pitfalls
- Putting required fields after fields with defaults: Like function parameters, required namedtuple fields must come before optional ones.
class Config(NamedTuple): port: int = 8080; host: strraisesTypeErrorbecausehost(no default) followsport(has default). - Using mutable default values:
defaults=[[], {}]shares the same mutable object across all instances. Unlike dataclassfield(default_factory=list), namedtuple defaults are not copied per instance. Use immutable defaults (tuples, frozensets, None) and create mutable objects after construction. - Confusing
defaultscount with field count: If you have 4 fields and passdefaults=[1, 2], the defaults apply to the last 2 fields, not the first 2. Fields without defaults remain required. - Modifying namedtuple fields directly: Namedtuples are immutable.
point.x = 10raisesAttributeError. Use_replace(x=10)to create a new instance with the modified value. - Using
namedtuplewhen you need mutability: If fields need to change after creation, use adataclassinstead. Converting between namedtuple and dataclass later requires changing all call sites that depend on tuple unpacking or indexing.
Summary
- Use
namedtuple("Name", fields, defaults=[...])for defaults in Python 3.6.1+ - Use
typing.NamedTuplewith class syntax for type hints and inline defaults - Defaults apply right-to-left — required fields must come first
- Use
_replace()to create modified copies (namedtuples are immutable) - Use
dataclassinstead when you need mutability, custom methods, or__post_init__ - Avoid mutable default values (
[],{}) — they are shared across instances

