Modern Python Types
NamedTuple Introduction
When you need lightweight, immutable data structures that are more readable than plain tuples, NamedTuples provide named field access while retaining tuple efficiency. They are memory-efficient, hashable, and work seamlessly with tuple unpacking.
Why Use NamedTuples?
Tuple Unpacking and _fields
NamedTuples support unpacking and provide metadata access through _fields and _asdict().
basic.py
# Basic namedtuple usage
from collections import namedtuple
# Create a namedtuple type
Point = namedtuple('Point', ['x', 'y'])
# Create instances
p1 =
p2 = Point(x=30, y=40)
# Access by name
print(f"p1: x={p1.x}, y={p1.y}")
# Access by index (still a tuple)
print(f"p1[0]={p1[0]}, p1[1]={p1[1]}")
# Tuple operations
print(f"Length: {len(p1)}")
print(f"As tuple: {tuple(p1)}")
# Basic namedtuple usage
from collections import namedtuple
# Create a namedtuple type
Point = namedtuple('Point', ['x', 'y'])
# Create instances
p1 =
p2 = Point(x=30, y=40)
# Access by name
print(f"p1: x={p1.x}, y={p1.y}")
# Access by index (still a tuple)
print(f"p1[0]={p1[0]}, p1[1]={p1[1]}")
# Tuple operations
print(f"Length: {len(p1)}")
print(f"As tuple: {tuple(p1)}")
# Basic namedtuple usage
from collections import namedtuple
# Create a namedtuple type
Point = namedtuple('Point', ['x', 'y'])
# Create instances
p1 =
p2 = Point(x=30, y=40)
# Access by name
print(f"p1: x={p1.x}, y={p1.y}")
# Access by index (still a tuple)
print(f"p1[0]={p1[0]}, p1[1]={p1[1]}")
# Tuple operations
print(f"Length: {len(p1)}")
print(f"As tuple: {tuple(p1)}")
typed_with_methods.py
# Typed NamedTuple with methods
from typing import NamedTuple
class Point(NamedTuple):
x: float
y: float
def distance_from_origin(self) -> float:
return (self.x ** 2 + self.y ** 2) ** 0.5
def distance_to(self, other: 'Point') -> float:
dx = self.x - other.x
dy = self.y - other.y
return (dx ** 2 + dy ** 2) ** 0.5
# Create points
p1 = Point(3.0, 4.0)
p2 = Point(6.0, 8.0)
print(f"p1 distance from origin: {p1.distance_from_origin():.2f}")
print(f"Distance from p1 to p2: {p1.distance_to(p2):.2f}")
default_values.py
# NamedTuple with default values
from typing import NamedTuple
class Person(NamedTuple):
name: str
age: int
country: str = "USA"
active: bool = True
# Use defaults
person1 = Person("Alice", 30)
print(person1)
# Override defaults
person2 = Person("Bob", 25, "Canada", False)
print(person2)
# Partial override
person3 = Person("Charlie", 35, country="UK")
print(person3)
immutable_replace.py
# Immutability and _replace()
from typing import NamedTuple
class Config(NamedTuple):
host: str
port: int
debug: bool
# Create config
config = Config("localhost", 8080, False)
print(f"Original: {config}")
# Cannot modify (immutable)
try:
config.port = 9000
except AttributeError as e:
print(f"Error: {e}")
# Use _replace() to create modified copy
new_config = config._replace(debug=True)
print(f"Modified: {new_config}")
print(f"Original unchanged: {config}")
# Multiple changes
prod_config = config._replace(host="0.0.0.0", port=80)
print(f"Production: {prod_config}")
unpacking_fields.py
# Tuple unpacking and _fields
from typing import NamedTuple
class Employee(NamedTuple):
name: str
id: int
department: str
salary: float
employee = Employee("Alice Johnson", 1001, "Engineering", 95000)
# Tuple unpacking
name, emp_id, dept, salary = employee
print(f"{name} (ID: {emp_id}) works in {dept}")
# Access _fields attribute
print(f"\nFields: {employee._fields}")
# Convert to dict using _asdict()
emp_dict = employee._asdict()
print(f"\nAs dict: {emp_dict}")
# Create from dict
data = {"name": "Bob Smith", "id": 1002, "department": "Sales", "salary": 85000}
new_employee = Employee(**data)
print(f"\nFrom dict: {new_employee}")
@seealso dataclass_intro "Dataclasses for mutable data" @seealso typing_intro "Type hints"
namedtuple A lightweight, immutable data structure that combines tuple efficiency with named field access, created using collections.namedtuple or typing.NamedTuple.
_replace() A method that creates a new NamedTuple instance with specified fields replaced, since NamedTuples are immutable and cannot be modified in place.
Exercise: practical.py
Create a Color NamedTuple with RGB values, hex conversion, and brightness calculation methods