Skip to content

namedtuple

A namedtuple is a tuple subclass with named fields. It combines the immutability of tuples with the readability of classes.

Mental Model

A namedtuple is a lightweight, immutable record — like a struct in C or a row in a spreadsheet. You get the memory efficiency and hashability of a tuple, but you access fields by name (point.x) instead of by cryptic index (point[0]). Use it whenever you need a simple data container without the overhead of a full class.


Creating Named Tuples

```python from collections import namedtuple

Define the type

Scientist = namedtuple('Scientist', ['name', 'field', 'born', 'nobel'])

Create instances

marie = Scientist('Marie Curie', 'physics', 1867, True) einstein = Scientist(name='Albert Einstein', field='physics', born=1879, nobel=True) ```

Alternative Field Definitions

```python

Space-separated string

Point = namedtuple('Point', 'x y z')

Comma-separated string

RGB = namedtuple('RGB', 'red, green, blue')

List of strings

Person = namedtuple('Person', ['name', 'age', 'city']) ```


Accessing Fields

By Name (like class)

```python Scientist = namedtuple('Scientist', ['name', 'field', 'born', 'nobel']) s = Scientist('Marie Curie', 'physics', 1867, True)

print(s.name) # Marie Curie print(s.field) # physics print(s.born) # 1867 print(s.nobel) # True ```

By Index (like tuple)

python print(s[0]) # Marie Curie print(s[1]) # physics print(s[-1]) # True

Slicing

python print(s[:2]) # ('Marie Curie', 'physics') print(s[1:3]) # ('physics', 1867)


Immutability

Named tuples are immutable like regular tuples:

```python s = Scientist('Marie Curie', 'physics', 1867, True)

s.name = 'M Curie' # AttributeError: can't set attribute s[0] = 'M Curie' # TypeError: 'Scientist' object does not support item assignment ```

Creating Modified Copies

Use _replace() to create a new instance with some fields changed:

python s = Scientist('Marie Curie', 'physics', 1867, True) s2 = s._replace(name='M. Curie', born=1867) print(s2) # Scientist(name='M. Curie', field='physics', born=1867, nobel=True) print(s) # Original unchanged


Comparison with Regular Class

Regular Class (Mutable)

```python class Scientist: def init(self, name, field, born, nobel): self.name = name self.field = field self.born = born self.nobel = nobel

s = Scientist('Marie Curie', 'physics', 1867, True) s.name = 'M Curie' # Works! (mutable) ```

namedtuple (Immutable)

```python from collections import namedtuple Scientist = namedtuple('Scientist', ['name', 'field', 'born', 'nobel'])

s = Scientist('Marie Curie', 'physics', 1867, True) s.name = 'M Curie' # AttributeError (immutable) ```


Utility Methods

Named tuples provide special methods (prefixed with _):

_fields

python print(Scientist._fields) # ('name', 'field', 'born', 'nobel')

_asdict()

```python s = Scientist('Marie Curie', 'physics', 1867, True) print(s._asdict())

{'name': 'Marie Curie', 'field': 'physics', 'born': 1867, 'nobel': True}

```

_make(iterable)

python data = ['Albert Einstein', 'physics', 1879, True] einstein = Scientist._make(data) print(einstein) # Scientist(name='Albert Einstein', ...)


Default Values

Use defaults parameter (Python 3.7+):

```python Scientist = namedtuple('Scientist', ['name', 'field', 'born', 'nobel'], defaults=[None, False])

'born' defaults to None, 'nobel' defaults to False

s = Scientist('Marie Curie', 'physics') print(s) # Scientist(name='Marie Curie', field='physics', born=None, nobel=False) ```


Use Cases

Function Return Values

```python def get_user_info(user_id): UserInfo = namedtuple('UserInfo', ['name', 'email', 'active']) return UserInfo('Alice', 'alice@example.com', True)

info = get_user_info(123) print(info.name) # Alice (more readable than info[0]) ```

Database Records

python Row = namedtuple('Row', ['id', 'name', 'price']) products = [ Row(1, 'Apple', 1.50), Row(2, 'Banana', 0.75), ] for p in products: print(f"{p.name}: ${p.price}")

Coordinates and Points

python Point = namedtuple('Point', ['x', 'y']) p1 = Point(3, 4) p2 = Point(0, 0) distance = ((p1.x - p2.x)**2 + (p1.y - p2.y)**2)**0.5


namedtuple vs typing.NamedTuple

For type hints, use typing.NamedTuple:

```python from typing import NamedTuple

class Scientist(NamedTuple): name: str field: str born: int nobel: bool = False # Default value

s = Scientist('Marie Curie', 'physics', 1867) print(s.nobel) # False ```


Summary

Feature tuple namedtuple class
Access by index
Access by name
Mutable
Hashable Depends
Memory Low Low Higher

Use namedtuple when:

  • You need readable field names
  • Immutability is desired
  • Memory efficiency matters
  • Simple data container without methods

Exercises

Exercise 1. Define a Color namedtuple with fields name, hex_code, and rgb (a tuple of three ints). Create a list of at least three colors and write a function find_by_name that takes the list and a color name string and returns the matching Color or None. For example, find_by_name(colors, "red") should return the red Color instance.

Solution to Exercise 1

```python from collections import namedtuple

Color = namedtuple('Color', ['name', 'hex_code', 'rgb'])

colors = [ Color('red', '#FF0000', (255, 0, 0)), Color('green', '#00FF00', (0, 255, 0)), Color('blue', '#0000FF', (0, 0, 255)), ]

def find_by_name(color_list, name): for color in color_list: if color.name == name: return color return None

Test

print(find_by_name(colors, "red"))

Color(name='red', hex_code='#FF0000', rgb=(255, 0, 0))

print(find_by_name(colors, "yellow"))

None

```


Exercise 2. Write a function csv_to_namedtuples that takes a CSV-formatted string (with a header row) and returns a list of namedtuples, where the namedtuple type is created dynamically from the header. For example, given "name,age\nAlice,30\nBob,25", it should return a list of Row(name='Alice', age='30') and Row(name='Bob', age='25').

Solution to Exercise 2

```python from collections import namedtuple

def csv_to_namedtuples(csv_string): lines = csv_string.strip().split('\n') headers = lines[0].split(',') Row = namedtuple('Row', headers) result = [] for line in lines[1:]: values = line.split(',') result.append(Row._make(values)) return result

Test

csv_data = "name,age\nAlice,30\nBob,25" rows = csv_to_namedtuples(csv_data) for row in rows: print(row)

Row(name='Alice', age='30')

Row(name='Bob', age='25')

print(rows[0].name) # Alice ```


Exercise 3. Define a Point namedtuple with fields x and y. Write a function translate that takes a Point and two offsets dx and dy, and returns a new Point shifted by those offsets using _replace(). Then write a function distance that takes two Point instances and returns the Euclidean distance between them.

Solution to Exercise 3

```python from collections import namedtuple import math

Point = namedtuple('Point', ['x', 'y'])

def translate(point, dx, dy): return point._replace(x=point.x + dx, y=point.y + dy)

def distance(p1, p2): return math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2)

Test

p = Point(3, 4) moved = translate(p, 1, -2) print(moved) # Point(x=4, y=2)

origin = Point(0, 0) print(distance(p, origin)) # 5.0 ```