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 namedtupleItem = namedtuple("Item", ["name", "price", "quantity"])
Here we first import namedtuple
from the collections
module in the standard library and then create a named tuple called Item
with the properties name
, price
and quantity
.
Now we can create objects of type Item
the same way would if Item
were a class.
ketchup = Item(name="Ketchup", price=1.00, quantity=10000)
We can also access the properties as you would expect.
>>> ketchup.price1.0>>> ketchup.quantity10000>>> toilet_paper.name'Ketchup'
All the properties we have defined for Item
are 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'>>>
We can however, pass a list of default values when creating the named tuple.
Item = namedtuple("Item", ["name", "price", "quantity", "is_dairy"], defaults=[False])
The default values are applied from right to left, so here is_dairy
defaults 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.00Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: can't set attribute>>>
But named tuples provide us with _replace
method which we can use to change values.
>>> ketchup._replace(price=2.00)Item(price=2.0, quantity=10000, name='Ketchup')>>>
For initializing a named tuple we can also use the _make
method 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])>>> pepperItem(price='Pepper', quantity=1.0, name=1)>>>
The Python documentation has an great example of using _make
to 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 _asdict
method 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)>>> mustardItem(price=1.0, quantity=10, name='Mustard')>>>
Note that as of Python 3.8, _asdict
returns 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_defaults
properties.
>>> ketchup._fields('name', 'price', 'quantity', 'is_dairy')>>> ketchup._field_defaults{'is_dairy': False}>>>
For more on named tuples you should check the Python documentation.