Namedtuple
TL;DR
collection.namedtuple
is a memory-efficient shortcut to defining an immutable class in Python manually.- Namedtuples can help clean up your code by enforcing an easier to understand structure on your data, which also improves readability.
- Namedtuples provide a few useful helper methods that all start with an
_
underscoreâbut are part of the public interface.
What is namedtuple
?
Pythonâs tuple is a simple immutable data structure for grouping arbitrary objects. It has two shortcomings:
- The data you store in it can only be pulled out by accessing it through integer indexes. You canât give names to individual properties stored in a tuple. This can impact code readability.
- Itâs hard to ensure that two tuples have the same number of fields and the same properties stored on them.
namedtuple
aims to solve these two problems. namedtuple is a factory function for making a tuple class. With that class we can create tuples that are callable by name also.
namedtuple
is immutable just like regular tuple- Once you store data in top-level attribute on a namedtuple, you canât modify it by updating the attribute.
- All attributes on a namedtuple object follow the âwrite once, read manyâ principle.
Each object stored in them can be accessed through a unique (human-readable) string identifier.
â This frees you from having to remember integer indexes, or resorting to workarounds like defining integer constants as mnemonics for your indexes. đ
How namedtuple
works?
Let’s take a look at an example:
from collections import namedtuple
User = namedtuple("User", ["name", "id", "gender"])
user = User("Ecko", 1, "male")
>>> user
User(name='Ecko', id=1, gender='male')
"User"
as the first argument to thenamedtuple
factory function is referred to as the âtypenameâ in the Python docs. Itâs the name of the new class thatâs being created by calling thenamedtuple
function, which needs to be explicitly specified.
The code above is equivalent to
class User:
def __init__(self, name, id, gender):
self.name = name
self.id = id
self.gender = gender
user = User("Ecko", 1, "male")
Why namedtuple
?
Namedtuple objects are implemented as regular Python classes internally. When it comes to memory usage, they are also âbetterâ than regular classes and just as memory efficient as regular tuples. đ
A good way to view them is to think that namedtuples are a memory-efficient shortcut to defining an immutable class in Python manually.
Operations
Unpacking
Tuple unpacking and the *
-operator for function argument unpacking also work as expected:
name, id, gender = user
print(f"name: {name}, id: {id}, gender: {gender}")
name: Ecko, id: 1, gender: male
print(*user)
Ecko 1 male
Accessing Values
Values can be accessed either by identifier or by index.
By identifier:
>>> user.name
Ecko
By index:
>>> user[0]
Ecko
Built-in Helper Functions
namedtuple
has some useful helper methods.
- Their names all start with an underscore character
_
- With
namedtuples
the underscore naming convention has a different meaning though: These helper methods and properties are part of namedtupleâs public interface. - The helpers were named that way to avoid naming collisions with user-defined tuple fields.
- With
_asdict
Returns the contents of a namedtuple
as a dictionary
>>> user._asdict()
OrderedDict([('name', 'Ecko'), ('id', 1), ('gender', 'male')])
This is great for avoiding typos in the field names when generating JSON-output, for example:
>>> import json
>>> json.dumps(user._asdict())
'{"name": "Ecko", "id": 1, "gender": "male"}'
We can convert a dictionary into a namedtuple
with **
operator
>>> user_dict = {"name": "Ben", "id": 2, "gender": "male"}
>>> User(**user_dict)
User(name='Ben', id=2, gender='male')
_replace()
Creates a (shallow) copy of a tuple and allows you to selectively replace some of its fields.
user._replace(id=2)
User(name='Ecko', id=2, gender='male')
_make()
Classmethod can be used to create new instances of a namedtuple from a sequence or iterable
User._make(["Ilona", 3, "female"])
User(name='Ilona', id=3, gender='female')
When to Use namedtuple
?
- If you’re going to create a bunch of instances of a class and NOT change the attributes after you set them in
__init__
, you can consider to usenamedtuple
.- Example: Definition of classes in
torchvision.datasets.cityscapes
- Example: Definition of classes in
- Namedtuples can be an easy way to clean up your code and to make it more readable by enforcing a better structure for your data. You should use
namedtuple
anywhere you think object notation will make your code more pythonic and more easily readable - But try NOT to use namedtuples for their own sake if they donât help you write âcleanerâ and more maintainable code.