There is a “special” type of tuples in Python that is called “named tuple”. It is quite common for Python learners to be confused about it, especially when and why we should use it.
A named tuple is a tuple, so it does everything that a tuple can. However, it is beyond a normal Python tuple. It is more like a “struct” in other programming languages such as C++. It is a specific subclass of a tuple that is programmatically created to your specification with named fields and fixed length.
In this article, I’ll introduce Python named tuples and try to demonstrate how to use it, when to use it and why we should use it.
1. Create a Named Tuple

Here is a small hint before we started. Since Python 3.1, there is an important built-in constant named tuple to indicate the version of the Python that we are using right now. We can get it as follows.
import sys
sys.version_info

If we want to use it in our program, we need to import it from the collection module.
from collections import namedtuple
The namedtuple
from the collection module is a class factory. In other words, it manufactures classes. We need to provide the following things to produce the class we want.
- The class name we want to use
- A sequence of field names we want to assign, in the order of elements in the tuple.
- We need to assign that class to a variable name in our code so we can use it to construct instances.
For example, if we want to define a Coords
class with two attributes, latitude and longitude, we can implement it as follows.
Coords = namedtuple('Coords', ['latitude', 'longitude'])
Then, we can use the Coords
class to instantiate an object, which will be a named tuple.
home = Coords(latitude=-37.8871270826, longitude=144.7558373041)

We can verify that it is a tuple, though it has field names.
isinstance(home, tuple)

Also, to instantiate a named tuple from the class, we don’t have to specify the field names every time, since the order and length of the named tuple are fixed.
home = Coords(-37.8871270826, 144.7558373041)

1.1 An Easy Way to Define a Named Tuple Class
Rather than using a list to specify the fields, we can easily use a string to do so. For example, we can use common to separate the field names.
Coords = namedtuple('Coords', 'latitude, longitude')

We can even use spaces as the delimiter, which is totally fine.
Triangle = namedtuple('Triangle', 'first_side second_side third_side')
t1 = Triangle(5, 5, 5)

1.2 Create from Superclass with Type Hints
Since Python 3.6, we can also define a named tuple class more formally. That will also support type hints for the named fields.
from typing import NamedTuple # 3.6+class Coords(NamedTuple):
"""A coordinate consists latitude and longitude"""
latitude: float
longitude: floathome = Coords(-37.8871270826, 144.7558373041)

The difference is that we need to use the NamedTuple
superclass from the typing module.
2. Field Name Auto-Renaming

When we are defining a named tuple class, although we may use strings for field names, they will be reflected to be class property. Therefore, there will be some limitations on these field names.
Firstly, we can’t use a field name that starts with an underscore.
MyNamedTuple = namedtuple('MyNamedTuple', ['_attr1', 'attr2'])

Some reserved keywords are also banned, such as def
.
MyNamedTuple = namedtuple('MyNamedTuple', ['def', 'attr2'])

Also, the field names cannot be duplicated, since a class cannot have two attributes with the same name.
MyNamedTuple = namedtuple('MyNamedTuple', ['attr1', 'attr1'])

However, since Python 3.1, we can set the flag rename
to True so that any invalid field names will be automatically renamed without throwing an error.
MyNamedTuple = namedtuple(
'MyNamedTuple',
['_attr1', 'def', 'attr2', 'attr2'],
rename=True
)
The named tuple definition in the above code has violated both the three rules, but because we set the rename flag to true, it will let it go without errors.
There is a little trick to check the field names of a named tuple class, which is using its private attribute _fields
.
MyNamedTuple._fields

3. Use a Named Tuple

To demonstrate how to use a named tuple, let’s repeat the example that we have used in the above sections. We can define the Coords
class and instantiate a named tuple home
.
Coords = namedtuple('Coords', 'latitude, longitude')
home = Coords(-37.8871270826, 144.7558373041)

3.1 Access the Values
Then, we can access the values in the named tuple. Very intuitively, we can use the field names to access their corresponding values. This is one of the major benefits of using named tuples. It also improves the readability of our codes.
print(home.latitude)
print(home.longitude)

Also, don’t forget a named tuple is a tuple. Therefore, we can use the index to get the values, too.
print(home[0])
print(home[1])

3.2 Convert a Named Tuple into a Dictionary
A named tuple is very similar to a dictionary in terms of its presentation. The field names can be considered as the keys of a dictionary, and they both have corresponding values.
Indeed, a named tuple has a built-in private method to convert itself into an Ordered Dictionary.
home._asdict()

This makes sense. Perhaps the most important difference between a named tuple and a dictionary is that the order of the fields matters in a named tuple. That means a named tuple and an ordered dictionary can be interchangeable.
However, what if we do not care about the order of the keys and we just want a dictionary? We can simply add one more typecasting to the ordered dictionary as follows.
dict(home._asdict())

3.3 Replace the Value of Field
Since a named tuple is a tuple, and tuples are immutable, it is impossible to change the value of a field.
home.latitude = 10

In this case, we have to use another private method _replace()
to replace values of the field.
home1 = home._replace(latitude=10)

The _replace()
method will return a new named tuple. That is important because we still cannot modify a named tuple even using this method.
If we check the original named tuple, it has not changed.

3.4 Named Tuple with Default Values
Just like in a normal class we can set default values for the properties, a named tuple class can also be set with default values. However, Since fields with a default value must come after any fields without a default, the defaults are applied to the rightmost parameters.
For example, let’s define the Coords
class again with only one default value.
Coords = namedtuple('Coords', 'latitude, longitude', defaults=[100])
home = Coords(-37.8871270826)
If we instantiate the named tuple with only one value, the default value 100
will be used for the longitude, which is the rightmost one in our definition.

What if we explicitly set the field to be the longitude, will the default value be used for the latitude?
home = Coords(longitude=-37.8871270826)

The answer is of course no. The order of the fields is pretty strict in a named tuple. To avoid confusion and potential issues, the default values have to be rightmost even we explicitly specify something.
If we give the default values to all the fields, which means that the number of provided default values is the same as the number of fields, we will not have to pass in any values when we instantiate a named tuple.
Coords = namedtuple('Coords', 'latitude, longitude', defaults=[-50, 100])
home = Coords()

A trick to check the default values of a named tuple class is to use its private property _field_defaults
.
Coords._field_defaults

3.5 Convert a Tuple to a Named Tuple
If we have a normal tuple and a named tuple class ready, we can easily convert the tuple into a named tuple using the private method _make()
. Please be noticed that the length of the tuple has to be the same as the named tuple.
t1 = (-37.8871270826, 144.7558373041)
home = Coords._make(t1)

4. Why and When to Use a Named Tuple?

Well, we have introduced almost everything about a named tuple in Python. Why does Python have it and when we should use it?
The answer is as follows:
- Compare with a normal tuple, using a named tuple could improve our code to have the semantics of tuple elements expressed.
- Compare to a Python class, using a named tuple could improve the code readability and reduce the lines of code significantly.
The first point is pretty self-explained. For the second one, let’s consider the following example. Suppose we need to define a Student
class. It does not necessarily have any methods. In other words, it just holds the data of a student object.
class Student:
def __init__(self, student_no, first_name, last_name, birth_year, gender):
self.student_no = student_no
self.first_name = first_name
self.last_name = last_name
self.birth_year = birth_year
self.gender = gender
If we use a named tuple, the definition is as simple as the follows.
Student = namedtuple('Student', 'student_no, first_name, last_name, birth_year, gender')
Therefore, for this scenario, using a named tuple is much easier and tidy than a class. However, if we need any class method, the named tuple will not be suitable anymore.
Another benefit of using a named tuple is its iterability. That is, a named tuple is iterable so that it can be used in many scenarios such as looping and generator.
Let’s use the Student
class to instantiate a named tuple
s1 = Student(123, 'Chris', 'Tao', 1900, 'Male')
Then, we can loop its values.
for attr in s1:
print(attr)

Summary
In this article, I have introduced the named tuple in Python, what it is, how to create a named tuple class and how to instantiate the class into named tuples. Then, I have illustrated when we should use a named tuple and when we shouldn’t. Hope you enjoy the reading!