A NamedTuple is a lightweight data structure provided by the collections module. It allows you to create tuple-like objects whose elements can be accessed using meaningful attribute names instead of only numeric indexes. Unlike a regular tuple, a NamedTuple makes code more readable because each value has a descriptive name.
Example: In this example, we create a Student NamedTuple and access its values using both an index and a field name.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "dob"])
s = Student("Emma", 20, "12-08-2005")
print(s[1])
print(s.name)
Output
20 Emma
Explanation:
- namedtuple() creates a new Student type with the fields name, age, and dob.
- s[1] accesses the second value using its index.
- s.name accesses the same object using the field name.
Syntax
namedtuple(typename, field_names)
Parameters:
- typename: Name of the NamedTuple class to create.
- field_names: List or string containing the names of the fields.
Return Value: Returns a new NamedTuple class that can be used to create objects.
Creating a NamedTuple
A NamedTuple is created using the namedtuple() function from the collections module. First, define the name of the NamedTuple and its fields, then create objects just like you would with a class.
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(x=1, y=2)
print(p.x, p.y)
Output
1 2
Explanation:
- namedtuple("Point", ["x", "y"]) creates a new NamedTuple type named Point with the fields x and y.
- Point(x=1, y=2) creates a Point object by assigning values to its fields.
- p.x and p.y access the values using their field names.
Accessing Values
A NamedTuple stores values in a fixed order, so its fields can be accessed in multiple ways. The most common methods are:
1. By Index: Since a NamedTuple behaves like a tuple, its values can be accessed using their index positions.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
s = Student("Emma", 20, "London")
print(s[1])
Output
20
Explanation:
- s[1] accesses the second value stored in the NamedTuple.
- Here, the value at index 1 is 20.
2. By keyname: Each value in a NamedTuple can also be accessed using its field name, making the code more readable.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
s = Student("Emma", 20, "London")
print(s.name)
Output
Emma
Explanation:
- s.name accesses the value stored in the name field.
- Using field names is generally preferred because it makes the code easier to understand.
3. Using getattr(): The built-in getattr() function can also retrieve a field value when the field name is available as a string.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
s = Student("Emma", 20, "London")
print(getattr(s, "city"))
Output
London
Explanation:
- getattr(s, "city") returns the value of the city field.
- This approach is useful when the field name is determined dynamically at runtime.
Conversion Operations
NamedTuple provides built-in methods to convert data between different Python data types. These methods are useful when working with lists, dictionaries, or when exchanging data between different parts of a program. Most commonly used conversion operations are:
1. Using _make(): creates a NamedTuple object from an iterable such as a list or tuple. The values must be in the same order as the fields.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
data = ["Emma", 20, "London"]
s = Student._make(data)
print(s)
Output
Student(name='Emma', age=20, city='London')
Explanation:
- Student._make(data) creates a Student NamedTuple from the list data.
- The list elements are assigned to the fields in the order they are defined.
2. Using _asdict(): converts a NamedTuple object into a dictionary, where the field names become keys.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
s = Student("Emma", 20, "London")
print(s._asdict())
Output
{'name': 'Emma', 'age': 20, 'city': 'London'}
Explanation:
- s._asdict() returns a dictionary containing all field names and their corresponding values.
- This is useful when you need dictionary-style access or want to serialize the data.
Note: In modern Python versions (3.8+), _asdict() returns a regular dict instead of an OrderedDict.
3. Using **: unpacks a dictionary and passes its key-value pairs as keyword arguments to create a NamedTuple.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
data = {"name": "Emma",
"age": 20,
"city": "London"}
s = Student(**data)
print(s)
Output
Student(name='Emma', age=20, city='London')
Explanation:
- Student(**data) unpacks the dictionary and matches its keys with the NamedTuple field names.
- The dictionary keys must exactly match the field names of the NamedTuple.
Additional Operations
NamedTuple also provides a few built-in attributes and methods that make it easier to inspect and work with its data. Most commonly used ones are:
1. Using _fields: returns a tuple containing the names of all the fields defined in the NamedTuple.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
s = Student("Emma", 20, "London")
print(s._fields)
Output
('name', 'age', 'city')
Explanation: s._fields returns a tuple containing all the field names of the Student NamedTuple.
2. Using _replace(): creates a new NamedTuple with one or more field values updated. The original NamedTuple remains unchanged because NamedTuples are immutable.
from collections import namedtuple
Student = namedtuple("Student", ["name", "age", "city"])
s = Student("Emma", 20, "London")
new_s = s._replace(city="Paris")
print(s)
print(new_s)
Output
Student(name='Emma', age=20, city='London') Student(name='Emma', age=20, city='Paris')
Explanation: s._replace(city="Paris") returns a new NamedTuple with the city field updated and original object s remains unchanged.