Using namedtuple and NamedTuple in Python
Python provides two ways to create tuple-like objects with named fields: the classic namedtuple function from the collections module and the modern NamedTuple class from the typing module. Both give you access to tuple elements by name while maintaining immutability.
namedtuple Basics
The namedtuple function creates a subclass of the built-in tuple with named fields. It is available in Python 2.6+ via the collections module.
from collections import namedtuple
# Create a namedtuple type
Point = namedtuple("Point", ["x", "y"])
# Instantiate with positional arguments
p = Point(10, 20)
# Access fields by name
print(p.x) # 10
print(p.y) # 20
# Access by index (inherited from tuple)
print(p[0]) # 10
print(p[1]) # 20
# Unpack like a regular tuple
x, y = p
print(x, y) # 10 20
You can also use a space-separated string instead of a list for field names:
Person = namedtuple("Person", "name age city")
NamedTuple (Python 3.6+)
NamedTuple is a newer approach that uses class syntax. It was introduced in Python 3.6 and provides better IDE support and type hints:
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
p = Point(5, 15)
print(p.x) # 5
print(p.y) # 15
The main advantage of NamedTuple over namedtuple is that it integrates with static type checkers. You can specify types for each field, making your code more maintainable in larger projects.
When to Use These Structures
Both namedtuple and NamedTuple are ideal when you need:
- Immutable data — once created, the values cannot change
- Lightweight records — simpler than full classes but more structured than plain tuples
- Named access — self-documenting code where field names clarify intent
- Tuple compatibility — can be used anywhere a tuple is expected
Common use cases include returning multiple values from functions, representing database rows, coordinate systems, and configuration objects.
Key Methods and Features
_replace() for Creating Modified Copies
Since namedtuples are immutable, use _replace() to create a new instance with modified fields:
from collections import namedtuple
User = namedtuple("User", "name email role")
original = User("alice", "alice@example.com", "admin")
# Create a modified copy
updated = original._replace(role="moderator")
print(updated) # User(name=alice, email=alice@example.com, role=moderator)
print(original) # Unchanged: User(name=alice, email=alice@example.com, role=admin)
_asdict() for Dictionary Conversion
Convert to an ordered dictionary:
p = Point(3, 4)
print(p._asdict()) # OrderedDict([(x, 3), (y, 4)])
Default Values (namedtuple only)
Use the defaults parameter (Python 3.7+) to provide default values:
from collections import namedtuple
Config = namedtuple("Config", ["host", "port", "debug"], defaults=["localhost", 8080, False])
c = Config("example.com")
print(c.host) # example.com
print(c.port) # 8080
print(c.debug) # False
Field Metadata (NamedTuple only)
NamedTuple allows adding metadata to fields:
from typing import NamedTuple
class Product(NamedTuple):
name: str
price: float
sku: str
# Works with static type checkers
def get_sku(product: Product) -> str:
return product.sku
Differences at a Glance
| Feature | namedtuple | NamedTuple |
|---|---|---|
| Type hints | No (unless using typing.NamedTuple) | Yes |
| Defaults | Yes (3.7+) | Yes (3.7+) |
| Inheritance | Limited | Full class features |
| IDE support | Basic | Full autocomplete |
| Syntax | Function call | Class definition |
dataclasses as an Alternative
For mutable records, consider the dataclasses module introduced in Python 3.7:
from dataclasses import dataclass
@dataclass
class User:
name: str
email: str
role: str = "guest"
user = User("bob", "bob@example.com")
user.role = "admin" # Mutable
See the dataclasses module reference for more details.
See Also
- collections module reference — for other collection utilities
- dataclasses module reference — for mutable record types
- built-in tuple — for tuple fundamentals