DEV Community

Juhana Jauhiainen
Juhana Jauhiainen

Posted on • Originally published at juhanajauhiainen.com

Using namedtuple to create simple data objects in Python

Python standard library has a handy collection factory function called namedtuple, which can be used to assign names for each position in a tuple.

Named tuples behave otherwise like a normal tuples but each element has a name which can be used for retrieving the value just like with class objects.

from collections import namedtuple
Item = namedtuple("Item", ["name", "price", "quantity"])
Enter fullscreen mode Exit fullscreen mode

Here we first import namedtuplefrom the collectionsmodule in the standard library and then create a named tuple called Itemwith the properties name, price and quantity.

Now we can create objects of type Itemthe same way would if Itemwere a class.

ketchup = Item(name="Ketchup", price=1.00, quantity=10000)
Enter fullscreen mode Exit fullscreen mode

We can also access the properties as you would expect.

>>> ketchup.price
1.0
>>> ketchup.quantity
10000
>>> toilet_paper.name
'Ketchup'
Enter fullscreen mode Exit fullscreen mode

All the properties we have defined for Itemare required so if you try to create a object without quantity we will get an error.

>>> mustard = Item(name="Mustard", price=1.00)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __new__() missing 1 required positional argument: 'quantity'
>>>
Enter fullscreen mode Exit fullscreen mode

We can however, pass a list of default values when creating the named tuple.

Item = namedtuple("Item", ["name", "price", "quantity", "is_dairy"], defaults=[False])
Enter fullscreen mode Exit fullscreen mode

The default values are applied from right to left, so here is_dairydefaults to False. The properties with default values hence have to be defined after the properties with required values.

Since tuples are immutable, we can't change the values by simple assignment.

>>> ketchup.price = 2.00
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>
Enter fullscreen mode Exit fullscreen mode

But named tuples provide us with _replacemethod which we can use to change values.

>>> ketchup._replace(price=2.00)
Item(price=2.0, quantity=10000, name='Ketchup')
>>>
Enter fullscreen mode Exit fullscreen mode

For initializing a named tuple we can also use the _makemethod which takes as its input a iterable. This means we can initialize our named tuple from a list, a standard tuple or any other object which implements the Python iterator protocol

>>> pepper = Item._make(["Pepper", 1.00, 1])
>>> pepper
Item(price='Pepper', quantity=1.0, name=1)
>>>
Enter fullscreen mode Exit fullscreen mode

The Python documentation has an great example of using _maketo initialize named tuples when reading data from a SQLite database or when reading a CSV file.

Named tuples can be easily converted to dictionaries and vice versa using the _asdictmethod and the double star operator

>>> ketchup._asdict()
{'name': 'Ketchup', 'price': 1.0, 'quantity': 10000, 'is_dairy': False}
>>>
>>> mustard_dict = {"name": "Mustard", "price": 1.00, "quantity": 10}
>>> mustard = Item(**mustard_dict)
>>> mustard
Item(price=1.0, quantity=10, name='Mustard')
>>>
Enter fullscreen mode Exit fullscreen mode

Note that as of Python 3.8, _asdictreturns a regular dict because they are now also ordered (since Python 3.7).

We can access the name of the fields and the default values programmatically using the _fields and _field_defaultsproperties.

>>> ketchup._fields
('name', 'price', 'quantity', 'is_dairy')
>>> ketchup._field_defaults
{'is_dairy': False}
>>>
Enter fullscreen mode Exit fullscreen mode

For more on named tuples you should check the Python documentation.

Top comments (1)

Collapse
 
juhanakristian profile image
Juhana Jauhiainen

This stackoverflow post has a nice explanation on the differences between namedtuple and a dataclass

stackoverflow.com/a/51673969/11849122