Python’s namedtuple is a game-changer when it comes to grouping related values in your code. This built-in data structure allows you to create new tuple types with named fields, making your code more expressive and readable. In this blog, we’ll explore the benefits of using Python namedtuple, how to create and use them, and real-world examples of when to use them. Let’s dive in and discover how namedtuple can simplify your Python code!
Are you interested in expanding your Python skills beyond the basics? Look no further! Check out our articles on decorators, generators, list comprehension, and more to take your Python skills to the next level!
What is namedtuple in Python?
Python’s namedtuple is a built-in data structure that combines the benefits of tuples and dictionaries.
A namedtuple is a subclass of a tuple that has named fields, which allows you to access its elements using both indexed positions and attribute names.
We can also say that, a namedtuple is a way of defining a lightweight class without defining an actual class.
Tuple vs Namedtuple
Namedtuple is similar to a regular tuple, but with some major differences:
|Definition||A collection of ordered and immutable elements||A subclass of tuple with named fields|
|Accessing Elements||Accessed using indexing||Accessed using indexing and named attributes|
|Field Naming||Not possible||Fields have named attributes|
|Length||Fixed length||Fixed length|
|Default Values||Not possible||Possible|
|Converting to Dictionary||Possible, but cumbersome||Easy using the _asdict() method|
Creating namedtuple in Python
NamedTuple provides a convenient way to define a data structure with a fixed number of elements. The elements of a namedtuple can be of any data type, such as integers, strings, lists, or even other namedtuples.
To define a namedtuple, you need to import the
namedtuple function from the
from collections import namedtuple
The syntax for creating a namedtuple is straightforward and easy to understand.
namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
Let’s now take some time to understand the parameters of namedtuple in Python:
typenameparameter: This is the name of the new namedtuple type that you want to create. It should be a valid Python identifier.
field_namesparameter: This is either a string or an iterable of strings that represent the names of the fields you want to define.
renameparameter: This is optional and defaults to False, determines whether invalid field names will be automatically renamed or raise a ValueError. If you set it to True, any invalid characters in field names will be replaced with underscores.
defaults: This parameter is also optional and allows you to set default values for one or more fields. It should be a dictionary that maps field names to their default values.
module: This is also optional and allows you to specify the module name that will be used when the namedtuple is printed or pickled. By default, it uses the main module.
Let’s look at an example of how to create a namedtuple in Python using these parameters:
Creating namedtuple using iterable & string
As Python list, dictionary, tuple and set are also iterables, these data structures can also be used to create namedtuple.
In this example we are just using list:
# defining fields as a string Person = namedtuple('Person', 'name age gender') # defining fields as an iterable Person = namedtuple('Person', ['name', 'age', 'gender'])
Note: If you’re using a string, the field names should be separated by whitespace or commas.
Using Rename in namedtuple
# renaming invalid field names Person = namedtuple('Person', ['name', 'age', '123'], rename=True) # output Person(name='John', age=25, _2=123)
Since the field name ‘123’ is not a valid Python identifier, using it as a field name would raise a
ValueError. However, the ‘rename’ argument is set to True, which means that invalid field names will be automatically renamed by replacing invalid characters with underscores.
Python namedtuple default values
# defining default values Person = namedtuple('Person', ['name', 'age', 'gender'], defaults=['Unknown']) # creating an instance without specifying gender person = Person('John', 25) # output Person(name='John', age=25, gender='Unknown')
Since gender value has not been passed while instance creation, the default value is used.
Using module parameter in namedtuple
Let’s take an example, In order to fully understand the module parameter and why it’s a useful feature in Python.
There are two separate modules:
address. Each module defines its own
namedtuple with different field names.
from collections import namedtuple Person = namedtuple('Person', ['name', 'age'], module=__name__)
from collections import namedtuple Address = namedtuple('Address', ['street', 'city', 'state'], module=__name__)
When defining the namedtuples, we use the
module=__name__ parameter to specify that the namedtuple should be attributed to the current module (i.e., the module where the namedtuple is defined).
This makes it clear which module each namedtuple belongs to and helps avoid naming conflicts with other modules.
Here’s an example of how you might use these namedtuples in another module:
from person import Person from address import Address p = Person('Alice', 30) a = Address('123 Main St', 'Anytown', 'CA') print(p) print(a)
In this example, we import the
Person namedtuple from the
person module, and the
Address namedtuple from the
address module. We then create instances of these namedtuples and print them to the console.
When we run this code, we get the following output:
Person(name='Alice', age=30) Address(street='123 Main St', city='Anytown', state='CA')
As you can see, the namedtuples are properly attributed to their respective modules, and we can use them to represent different types of data in our code.
Creating Empty namedtuple in Python
Sometimes you may want to create a namedtuple without any initial values. This is particularly useful when you want to populate the namedtuple with values later on in your code.
Fortunately, creating an empty namedtuple in Python is just as easy as creating a named tuple with values.
To create an empty namedtuple, simply call the namedtuple constructor with the name of your new namedtuple type and an empty string of field names.
from collections import namedtuple Person = namedtuple('Person', '') # create an empty Person instance person = Person() # add values to the fields person = person._replace(name='John Doe', age=25, gender='Male')
Note: You can’t use the standard indexing syntax to add values to an empty namedtuple because it doesn’t have any fields defined. Instead, you must use the
_replace() method to create a new instance of the namedtuple with the new values.
Creating NamedTuple with typing package
In addition to using the collections
namedtuple function to create a new namedtuple, you can also use the
typing.NamedTuple class to define your own namedtuples.
This class provides a more modern and intuitive syntax for defining namedtuples, and it also allows you to specify default values for your fields.
Here’s an example of how to use
typing.NamedTuple to define a new namedtuple:
from typing import NamedTuple class Person(NamedTuple): name: str age: int gender: str = 'Unknown'
Creating a new instance of this NamedTuple is as simple as calling the
Person constructor with the appropriate arguments:
# create a new Person instance person = Person('Hack The Developer', 17) # access the name attribute print(person.name) # access the age attribute print(person.age) # access the gender attribute print(person.gender)
Hack The Developer 17 Unknown
As you can see, we can access the attributes of the
Person instance just like we would with a regular namedtuple.
Using Type Hints with Python namedtuple
Type hints are an increasingly popular way to enhance code clarity and robustness, and Python’s namedtuple is no exception.
By adding type hints to your namedtuple definitions, you can ensure that your code is more readable and less prone to errors.
To add type hints to your namedtuple, simply include the type annotations as you would with any other Python function or class.
from typing import Tuple Person = namedtuple('Person', [('name', str), ('age', int), ('gender', str)]) -> Tuple[str, int, str]
Python namedtuple: collections vs typing
While the two are similar in many ways, there are a few key differences that may make one more appropriate for your use case than the other.
|Inheritance||Subclass of tuple||Subclass of tuple|
|Field definition||String of space-separated field names||Class attributes|
|Default values||Defined using ||Defined using attribute assignment|
|Type hinting||No support||Supported|
|Attribute access||Accessible via named attributes or index||Accessible via named attributes only|
Instantiating namedtuple with _make function
_make function provides a shortcut that can save you time and effort to create new namedtuple instances with named fields.
Here’s what you need to do for instantiating namedtuple with
- Define your namedtuple type
from collections import namedtuple Person = namedtuple('Person', ['name', 'age', 'gender'])
- Create a list or tuple of values for each field
person_values = ['John Doe', 25, 'Male']
- Use the
_makefunction to create a new instance
person = Person._make(person_values)
And that’s it! You’ve created a new Person instance with named fields using the values in your list or tuple.
This shortcut is especially useful when you have a large number of field values or when you want to create instances dynamically.
Here’s a more complete example that demonstrates the power of using _make:
# define a new namedtuple type Person = namedtuple('Person', ['name', 'age', 'gender']) # create a list of person values person_values = [ ['Divyanshu Shekhar', 21, 'Male'], ['Arpit Sahu', 21, 'Male'], ['Shubham Ranjan', 21, 'Male'] ] # create a list of Person instances using _make people = [Person._make(values) for values in person_values] # print the names of all people for person in people: print(person.name)
Divyanshu Shekhar Arpit Sahu Shubham Ranjan
As you can see, using _make allows you to create new instances of a namedtuple with less code and more readability.
So next time you need to create a new namedtuple instance, give _make a try and see how it can simplify your code!
Accessing namedtuple in Python
Accessing a namedtuple in Python is incredibly easy and intuitive.
There are four ways you can access a namedtuple in python:
- Offset Notation
- Dot Notation
- Using getattr() function
Here is an example to demonstrate how to access the elements of a namedtuple using different ways as discussed above:
# Create an instance of the Person namedtuple person = Person(name='John Doe', age=25, gender='Male') # Accessing elements using indexing print(person) # Output: John Doe print(person) # Output: 25 print(person) # Output: Male # Accessing elements using named attributes print(person.name) # Output: John Doe print(person.age) # Output: 25 # Unpacking the namedtuple name, age, gender = person print(name) # Output: John Doe print(age) # Output: 25 # Access using getattr() print(getattr(person, 'name')) # Output: John Doe print(getattr(person, 'age')) # Output: 25
Convert a Python namedtuple to a Dictionary
One of the most useful features of Python namedtuple is its ability to be converted easily to a dictionary.
To convert a namedtuple to a dictionary, you can use the
_asdict() method, which returns an ordered dictionary representing the named tuple.
from collections import namedtuple Person = namedtuple('Person', ['name', 'age', 'gender']) person = Person(name='John Doe', age=25, gender='Male') # convert the namedtuple to a dictionary person_dict = person._asdict() print(person_dict)
OrderedDict([('name', 'John Doe'), ('age', 25), ('gender', 'Male')])
This feature of Python namedtuple can be particularly useful when working with data that needs to be serialized or sent over the network.
By converting a namedtuple to a dictionary, you can easily convert it to a JSON or XML representation, or any other format that expects dictionary-like objects.
Change Field Values in Python namedtuple
Python namedtuple not only makes it easy to access the fields of a tuple, but it also allows you to replace or modify the values of those fields.
To change a field value in a namedtuple, we can use the built-in
# create a new Person instance Person = namedtuple('Person', ['name', 'age', 'gender']) person = Person(name='John Doe', age=25, gender='Male') # change the value of the age field person = person._replace(age=30) # print the updated Person instance print(person)
Person(name='John Doe', age=30, gender='Male')
Iterate over Python namedtuple fields
_fields attribute can be used to get all the field names of a namedtuple as it returns a tuple of all the field names of the namedtuple type:
print(Person._fields) # ('name', 'age', 'gender')
Iterate over the fields of the namedtuple:
from collections import namedtuple Person = namedtuple('Person', ['name', 'age', 'gender']) person = Person(name='John Doe', age=25, gender='Male') for field in person._fields: print(field)
How to Compare namedtuples
Python namedtuples are a great way to group related data together, but what if you need to compare them? Python makes it easy to compare namedtuples using built-in methods.
There are two ways of comparing namedtuples in python:
- Using equality operator (
Let’s see both of them in action:
The first method is the
== operator, which compares two namedtuples for equality. It compares each field in the namedtuples for equality, and returns
True if all fields are equal.
from collections import namedtuple Person = namedtuple('Person', ['name', 'age', 'gender']) person1 = Person(name='John Doe', age=25, gender='Male') person2 = Person(name='Jane Doe', age=25, gender='Female') # compare person1 and person2 print(person1 == person2) # Output: False person3 = Person(name='John Doe', age=25, gender='Male') # compare person1 and person3 print(person1 == person3) # Output: True
Another method to compare namedtuples is the
._fields attribute, which returns a tuple of the field names in the namedtuple.
You can use this attribute to ensure that two namedtuples have the same fields before comparing them.
from collections import namedtuple Person = namedtuple('Person', ['name', 'age', 'gender']) Address = namedtuple('Address', ['street', 'city', 'state']) person = Person(name='John Doe', age=25, gender='Male') address = Address(street='123 Main St', city='Anytown', state='CA') # compare person and address if person._fields == address._fields: print("Cannot compare person and address because they have different fields") else: print("Comparing person and address")
Python namedtuple inheritance
Inheriting from a Python namedtuple is an excellent way to take advantage of the built-in functionality while adding your own customizations.
Inheriting allows you to create a new namedtuple type that inherits the properties of the parent namedtuple, as well as any methods or attributes that you add to the child class.
To inherit from a Python namedtuple, you simply need to create a new class and make the parent namedtuple the base class of the new class.
from collections import namedtuple # create a parent namedtuple Person = namedtuple('Person', ['name', 'age', 'gender']) # create a child namedtuple that inherits from the parent namedtuple class Employee(Person): def __init__(self, name, age, gender, employee_id): super().__init__(name, age, gender) self.employee_id = employee_id def get_employee_id(self): return self.employee_id
Now let’s create an instance of the child class and see how it works:
# create a new Employee instance employee = Employee(name='Hack The Developer', age=25, gender='Male', employee_id='1234') # access the inherited attributes print(employee.name) print(employee.age) print(employee.gender) # access the new attribute and method print(employee.employee_id) print(employee.get_employee_id())
Hack The Developer 25 Male 1234 1234
As you can see, we can access the attributes of the parent namedtuple using the named attributes of the child namedtuple.
We can also access the new attribute and method that we added to the child class.
Advantages of Python namedtuple
Python’s namedtuple offers several advantages over other data structures. Let’s take a look at a few of them:
- Simplicity: namedtuple is a simple and straightforward way to group related values together. You can create a new namedtuple type with just a few lines of code, saving you time and effort.
- Readability: Namedtuples make your code more readable and easier to understand. By giving each field a descriptive name, you can quickly identify the purpose of each value, making it easier to maintain and debug your code.
- Ease of use: Namedtuples allow you to access values using both named attributes and positional indexing, giving you the flexibility to choose the method that works best for your use case.
- Default values: You can easily set default values for fields in a namedtuple, making your code more robust and less prone to errors.
- Immutability: Namedtuples are immutable, meaning you cannot modify the values once they are set. This is a useful feature when you want to ensure that your data is not accidentally changed during runtime.
- Serialization: You can easily convert namedtuples to dictionaries or JSON, making them compatible with external APIs or data storage systems that expect these formats.
In this blog, we’ve explored the power and versatility of Python namedtuple. We’ve seen how it allows you to group related values together in a simple and elegant way, and how it offers many advantages over other data structures. By using namedtuple, you can make your code more readable and easier to understand, while also saving time and effort.
We’ve covered how to create and use namedtuple, as well as its advantages and practical examples of when to use it. Now that you’ve seen the benefits of using Python namedtuple, it’s time to start incorporating it into your own code.
Whether you’re a beginner or an experienced Python programmer, namedtuple is a valuable tool to have in your coding arsenal. So go ahead, give it a try, and see for yourself how it can revolutionize the way you write Python code!
- Python documentation on namedtuple
- Python documentation on tuples: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences