namedtuple
collection in Python is part of the collections
module. it provides a simple way to create lightweight object types similar to tuples, but with named fields. Named fields in namedtuple
allows for improved code readability and usability compared to traditional tuples.
namedtuple
namedtuple
collection in Python, allows us to create classes which are immutable tuples but with named fields. This is a subclass of Python’s built-in tuple
. Named fields make the tuple elements more readable because then we can access elements by names rather than indices.
Syntax to create namedtuple
object:
namedtuple_class = collections.namedtuple(typename, field_names, rename=False, defaults=(fields), module=None)
)
collections
is a module in Python.namedtuple
class is part ofcollections
module. We need to importcollections
module to usenamedtuple
class in our program.namedtuple()
is thenamedtuple
class constructortypename
is the name of the class. This name can be used to define values to the named fields.field_names
are the space separated field names. We can pass these name as a list as well.rename
attribute default value isFalse
. IfTrue
, then this attribute will rename the keyword names given as field names.namedtuple_class
is the class returned with typename and fields.defaults
– These are default values used in case values provided are less than field names. Multiple default values can be provided as tuple. These values can be used for right side field names.module
– Default value for module attribute isNone
. if module is defined, the__module__
attribute of the named tuple is set to that value.
namedtuple
Properties
- It defines the element values for the given field name. Named fields are easier to access, instead of relying on positional indexing.
- This class object are immutable similar to tuple.
- Lightweight and memory-efficient compared to normal classes.
- Number of values provided for object should not be more than the number of field names. Otherwise,
TypeError
will be raised. field_names
should be starting with underscore and should not be using any Python keyword or identifiers. OtherwiseValueError
will be raised.
namedtuple
Class and Object
Create There are multiple ways, using which we can create namedtuple
class object.
- Using typename and fieldnames
- Using typename, fieldnames and rename
- Using typename, fieldnames, rename and default values
Using typename and fieldnames
from collections import namedtuple
# Scenario 1 - create named tuple with default settings
print("create named tuple with default settings")
namedtuple_object = namedtuple('shbytes',['c1','c2','c3']) # field names passed as list
# create object from namedtuple class and assign values to fields
o = namedtuple_object('AWS','Python','DevOps')
print(o)
print(type(o))
# Scenario 2 - create named tuple with field names passed with space separated
print("create named tuple with field names passed with space separated")
shbytes_object = namedtuple('shbytes',"c1 c2 c3") # field names passed with space separated
# create object from namedtuple class and assign values to fields
o = shbytes_object('AWS','Python','DevOps')
print(o)
print(type(o))
# Scenario 3 - create named tuple with field names cannot start with underscore
print("create named tuple with field names cannot start with underscore")
try:
shbytes = namedtuple('shbytes',['_c1', '_c2']) # field names start with underscore not allowed
except ValueError as err:
print("error", err)
# Scenario 4 - named tuple - invalid field names
print("named tuple - invalid field names")
try:
shbytes = namedtuple('shbytes',['c1', 'def', 'c1'])
except ValueError as err:
print("error", err)
We are looking for four scenarios while creating the namedtuple
class.
- Field names are passed as list =>
namedtuple('shbytes',['c1','c2','c3'])
and then we use the class object to assign the values to the fields and createnamedtuple_object
. - Space separated field names passed as string =>
namedtuple('shbytes',"c1 c2 c3")
- Field name start with underscore will given an
ValueError
=>namedtuple('shbytes',['_c1', '_c2'])
- Python keyword identifier is given as field name. In this case ValueError will be raised =>
namedtuple('shbytes',['c1', 'def', 'c1'])
.def
is a Python identifier used as field name.
Program Output
create named tuple with default settings
shbytes(c1='AWS', c2='Python', c3='DevOps') # namedtuple with field values
<class '__main__.shbytes'> # type is the typename given for class
create named tuple with field names passed with space separated
shbytes(c1='AWS', c2='Python', c3='DevOps') # namedtuple with field values
<class '__main__.shbytes'>
create named tuple with field names cannot start with underscore
error Field names cannot start with an underscore: '_c1' # Error when field names start with underscore
named tuple - invalid field names
error Type names and field names cannot be a keyword: 'def'
From the Program Output,
- In the first scenario, we got the
namedtuple
class object =>shbytes(c1='AWS', c2='Python', c3='DevOps')
- In the second scenario also we got similar
namedtuple
class object =>shbytes(c1='AWS', c2='Python', c3='DevOps')
- In third scenario,
ValueError
was raised because field names were started with underscore. - In fourth scenario,
ValueError
was raised because Python keyword identifier was used as a field name .
Using typename, fieldnames and rename
We cannot create a namedtuple
class with the field names start with underscore or with field names which are keyword identifier defined in Python. To create a namedtuple
class with these field names, we can use rename
attribute as True
.
By default, rename
attribute is False
for namedtuple
. With rename = True
, invalid field names are renamed with positional values.
from collections import namedtuple
# Scenario 1 - invalid field names are replaced with positional name
print("invalid field names are replaced with positional name")
shbytes_object = namedtuple('shbytes',['_c1', '_c2'], rename=True)
o = shbytes_object('Python','Power BI')
print(o)
print(type(o))
# Scenario 2 - invalid field names are replaced with positional names
print("named tuple - invalid field names are replaced with positional names")
shbytes_object = namedtuple('shbytes',['c1','def','c1'], rename=True)
o = shbytes_object('AWS','Python','Power BI')
print(o)
print(type(o))
- In the first case, field name are starting with underscore which is invalid. We are creating a
namedtuple
class withrename
attribute =>namedtuple('shbytes',['_c1', '_c2'], rename=True)
- In second case, Python keyword identifiers are given as field name and a duplicate field name is used =>
namedtuple('shbytes',['c1','def','c1'], rename=True)
.def
is a keyword identifier.c1
is used second time.
Program Output
invalid field names are replaced with positional name
shbytes(_0='Python', _1='Power BI')
<class '__main__.shbytes'>
named tuple - invalid field names are replaced with positional names
shbytes(c1='AWS', _1='Python', _2='Power BI')
<class '__main__.shbytes'>
- In first case
namedtuple
class fields was replaced with_0
and_1
=>shbytes(_0='Python', _1='Power BI')
- In the second case,
def
field name was replaced with_1
andc1
duplicate field name is replaced with_2
=>shbytes(c1='AWS', _1='Python', _2='Power BI')
Using rename and default values
We can use defaults
attribute while creating the namedtuple
class. defaults
attribute provides the default values to the fields of namedtuple
.
- While creating the
namedtuple
object, if number of field names are more than the number of values provided, then default values can be assigned to those extra fields. - Number of values provided for object should not be more than the number of field names. Otherwise,
TypeError
will be raised.
from collections import namedtuple
# Scenario 1 - named tuple - default value applied to right most parameters
print("named tuple - default value applied to right most parameters")
shbytes_class = namedtuple('shbytes',['c1','c1','c2'], rename=True, defaults=('Python','Power BI'))
o = shbytes_class('AWS')
print(o)
print(type(o))
# Scenario 2 - named tuple - default value is ignored if no parameter left to assign
print("named tuple - default value applied to right most parameters")
shbytes_class = namedtuple('shbytes',['c1','c1','def'], rename=True, defaults=('Python', 'Azure',))
o = shbytes_class('AWS', 'Power BI')
print(o)
print(type(o))
# Scenario 3 - named tuple - Total count of values and default values is less than field names
print("named tuple - Total count of values and default values is less than field names")
try:
shbytes_class = namedtuple('shbytes', ['c1', 'c1', 'def'], rename=True, defaults=('Python',))
o = shbytes_class('Power BI')
except TypeError as err:
print("error", err)
# Scenario 4 - named tuple - more values than field names
print("named tuple - more values than field names")
try:
shbytes_class = namedtuple('shbytes', ['c1', 'c1', 'def'], rename=True)
o = shbytes_class('AWS', 'DevOps', 'Python', 'Power BI')
except TypeError as err:
print("error", err)
- In first scenario, we are using
defaults=('Python','Power BI')
to createnamedtuple
class. Total field names given are 3. We are passing only 1 value while creating the class objecto = shbytes_class('AWS')
. Values for 2 extra field names will be taken from default values. - In second scenario, we are again using defaults=(‘Python’, ‘Azure’,) to create
namedtuple
class. Total field names are 3 and we are passing 2 values while creating the class objecto = shbytes_class('AWS', 'Power BI')
. Value for 1 extra field name will be taken from default values and 1 default value will remain unused. - In third scenario, we are creating a namedtuple class with 1 default value and class object with 1 value. But field names are 3. Total count of default values and values in class object is 2, which is less than number of field names. This will raise
TypeError
=>missing 1 required positional argument
- In third scenario, we are creating a namedtuple with 3 field names and class object with 4 value. Total number of values in class object is more than number of field names. This will also raise
TypeError
=>takes 4 positional arguments but 5 were given
Program Output
named tuple - default value applied to right most parameters
shbytes(c1='AWS', _1='Python', c2='Power BI')
<class '__main__.shbytes'>
named tuple - default value applied to right most parameters
shbytes(c1='AWS', _1='Power BI', _2='Azure')
<class '__main__.shbytes'>
named tuple - Total count of values and default values is less than field names
error shbytes.__new__() missing 1 required positional argument: '_1'
named tuple - more values than field names
error shbytes.__new__() takes 4 positional arguments but 5 were given
namedtuple
Access Elements in There are multiple ways to access elements in a namedtuple
object.
- Access elements with the field name
- Access elements with the index position
- Elements unpacked like in a tuple
- Using the
getattr(namedtuple, variable)
method
from collections import namedtuple
# Scenario 1 - namedtuple elements can be accessed with field name
print("namedtuple elements can be accessed with field name")
shbytes_class = namedtuple('shbytes',['c1','c2','c3'])
o = shbytes_class('AWS','Python','DevOps')
print("c1 - ", o.c1)
print("c2 - ", o.c2)
print("c3 - ", o.c3)
# Scenario 2 - namedtuple elements can be accessed with index
print("namedtuple elements can be accessed with index")
shbytes_class = namedtuple('shbytes',['c1','c2','c3'])
o = shbytes_class('AWS','Python','DevOps')
print("c1 - ", o[0])
print("c2 - ", o[1])
print("c3 - ", o[2])
# Scenario 3 - namedtuple elements can be unpacked like tuple
print("namedtuple elements can be unpacked like tuple")
shbytes_class = namedtuple('shbytes',['c1','c2','c3'])
o = shbytes_class('AWS','Python','DevOps')
l, m, n = o
print(l, m, n)
# Scenario 4 - getattr(namedtuple, variable) - to get value for an attribute
print("getattr(namedtuple, variable) - to get value for an attribute")
shbytes_class = namedtuple('shbytes',['c1','c2','c3'])
o = shbytes_class('Python', 'AWS', 'Power BI')
value_c1 = getattr(o, 'c1')
print(value_c1)
print(getattr(o, 'c2'))
print(getattr(o, 'c3'))
In all scenarios, we are creating a namedtuple
class with namedtuple('shbytes',['c1','c2','c3'])
and object with o = shbytes_class('AWS','Python','DevOps')
. Number of field names and values passed are equal. Each field name will assigned value in order from left to right.
- In first scenario, we are accessing values based on the field names like
o.c1
,o.c2
,o.c3
. - In second scenario, we are accessing values based on the index positions like
o[0]
,o[1]
,o[2]
. - In third scenario, we are using unpack of object elements like
l, m, n = o
. Elements values (from left to right) will be assigned to these unpack variables and then can be used. - In fourth scenario, we are accessing values using
getattr
method.value_c1 = getattr(o, 'c1')
=> we are passing object and field name whose value to be accessed.
Program Output
namedtuple elements can be accessed with field name
c1 - AWS
c2 - Python
c3 - DevOps
namedtuple elements can be accessed with index
c1 - AWS
c2 - Python
c3 - DevOps
namedtuple elements can be unpacked like tuple
AWS Python DevOps
getattr(namedtuple, variable) - to get value for an attribute
Python
AWS
Power BI
namedtuple
Method with There are multiple built-in methods applicable with namedtuple
class.
_make(iterable)
– This method used to create another instance ofnamedtuple
_asdict()
– This method returns dictionary with values mapped to named parameters_replace(**kwargs)
– This method replaces the specified fields with new values and returns a new instance ofnamedtuple
_make(iterable)
from collections import namedtuple
# Scenario 1 - _make(iterable) - method used on namedtuple object to create another instance
print("_make(iterable) - method used on namedtuple object to create another instance")
Courses = namedtuple('Courses',['c1','c2','c3'])
course_tuple = Courses('AWS','Python','DevOps')
print(course_tuple)
o = course_tuple._make(course_tuple) # _make used on object
print(o)
# Scenario 2 - _make(iterable) - method used on namedtuple class to create another instance
print("_make(iterable) - method used on namedtuple class to create another instance")
Courses = namedtuple('Courses',['c1','c2','c3'])
level_tuple = Courses._make(["beginner", "intermediate", "expert"]) # _make used on class
print(level_tuple)
In both scenarios, we are creating a namedtuple
class Courses
with namedtuple('Courses',['c1','c2','c3'])
.
- In first scenario, we are creating
namedtuple
objectCourses('AWS','Python','DevOps')
and then we are using_make()
method on this object to create anothernamedtuple
object =>o = course_tuple._make(course_tuple)
- In second scenario, we are using
_make()
method on the class to createnamedtuple
object =>level_tuple = Courses._make(["beginner", "intermediate", "expert"])
Program Output
_make(iterable) - method used on namedtuple object to create another instance
Courses(c1='AWS', c2='Python', c3='DevOps')
Courses(c1='AWS', c2='Python', c3='DevOps') # object created using _make() method
_make(iterable) - method used on namedtuple class to create another instance
Courses(c1='beginner', c2='intermediate', c3='expert') # object created using _make() method
_asdict()
Method
_asdict()
method returns dictionary with values mapped to named parameters.
from collections import namedtuple
# _asdict() - method returns dictionary with values mapped to named parameters
print("_asdict() - method returns dictionary with values mapped to named parameters")
Courses = namedtuple('Courses',['c1','c2','c3'])
course_tuple = Courses('AWS','Python','DevOps')
print(course_tuple) # namedtuple object
print(type(course_tuple)) # type of namedtuple object
course_dict = course_tuple._asdict() # convert to dictionary
print(course_dict) # dictionary object
print(type(course_dict)) # type of dictionary object
course_tuple._asdict()
to convert the namedtuple
object to dictionary key-value pair.
Program Output
_asdict() - method returns dictionary with values mapped to named parameters
Courses(c1='AWS', c2='Python', c3='DevOps') # namedtuple object
<class '__main__.Courses'> # type of namedtuple object
{'c1': 'AWS', 'c2': 'Python', 'c3': 'DevOps'} # dictionary object created using _asdict() method
<class 'dict'> # type of dictionary object
_replace(**kwargs)
Method
_replace(**kwargs)
method replaces the specified fields with new values and returns a new instance of namedtuple
.
from collections import namedtuple
# _replace(**kwargs) - method returns a new instance of namedtuple
# replacing the specified fields with new values
print("_replace(**kwargs) - method returns a new instance of namedtuple")
Courses = namedtuple('Courses',['c1','c2','c3'])
course_tuple = Courses('AWS','Azure','DevOps')
print(course_tuple) # original namedtuple object
replaced_course_tuple = course_tuple._replace(c2='Python',c3='ML') # values replaced using _replace() method
print(replaced_course_tuple) # new object with replaced values
course_tuple._replace(c2='Python',c3='ML')
will replace the values of fields c2
and c3
with the new values.
Program Output
_replace(**kwargs) - method returns a new instance of namedtuple
Courses(c1='AWS', c2='Azure', c3='DevOps') # original object elements
Courses(c1='AWS', c2='Python', c3='ML') # replaced object elements
namedtuple
attributes – _fields
and _field_defaults
_fields
is anamedtuple
attribute and used to list the field names_field_defaults
attribute is used to return the mapping field names to default values
from collections import namedtuple
# _fields - strings listing the field names
print("_fields - strings listing the field names")
Coordinates = namedtuple('Coordinates',['lat','long'])
c = Coordinates(-34.0667,46.8231)
print(c) # namedtuple object
print(c._fields) # Returns the field names as tuple
#_field_defaults - Dictionary mapping field names to default values
print("_field_defaults - Dictionary mapping field names to default values")
shbytes = namedtuple('shbytes', ['c1','c2','c3'], defaults=['Power BI','Python'])
print(shbytes._field_defaults) # Returns fields mapped to default values
Program Output
_fields - strings listing the field names
Coordinates(lat=-34.0667, long=46.8231)
('lat', 'long') # Field names returned using _fields attribute
_field_defaults - Dictionary mapping field names to default values
{'c2': 'Power BI', 'c3': 'Python'} # Field names mapped to default values
Summary
In this article, we learned about namedtuple
collection in Python. Following topics were discussed:
- namedtuple
- Create namedtuple Class and Object
- Access Elements in namedtuple
- Method with namedtuple
- namedtuple attributes – _fields and _field_defaults
Code – Github Repository
All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.
Python Topics
Interview Questions & Answers
namedtuple
from the dictionary object?
Q: How can we create a from collections import namedtuple
# convert dictionary to a namedtuple using double-star-operator
print("convert dictionary to a namedtuple using double-star-operator")
Courses = namedtuple('Courses', ['c1', 'c2'])
course_dict = {'c1':'Python', 'c2':'AWS'}
print(course_dict)
print(Courses(**course_dict))
In this program, we have defined a namedtuple
class Courses
with namedtuple('Courses', ['c1', 'c2'])
. We have also defined a dictionary {'c1':'Python', 'c2':'AWS'}
. Dictionary keys and namedtuple class fields are same. Using Courses(**course_dict)
we are converting dictionary elements to namedtuple object.
Dictionary keys and namedtuple field names should be same, otherwise TypeError
will be raised.
namedtuple
compare to a dictionary?
Q: How does namedtuple
are immutable, we cannot perform any modification after object is created. Field names are predefined, improving code readability and predictability. namedtuple
are lightweight and memory efficient.
dictionary
are mutable, key-value pairs and we can perform update operations after object is created. We can create dictionaries with dynamic keys that are not predefined, this makes them more flexible but sometimes less predictable. Dictionary object consume larger memory compared to namedtuple
.
namedtuple
?
Q: Can we create a nested Nested namedtuple
can be created. We can use one namedtuple
as a field inside another namedtuple
.
Point = namedtuple('Point', 'x y')
Rectangle = namedtuple('Rectangle', 'top_left bottom_right')
# Create instances of Point
p1 = Point(0, 0)
p2 = Point(10, 10)
# Create an instance of Rectangle using Point
rectangle = Rectangle(top_left=p1, bottom_right=p2)
print(rectangle) # Output => Rectangle(top_left=Point(x=0, y=0), bottom_right=Point(x=10, y=10))