DEV Community

Cover image for Python's Collections Module: namedtuple
Kathan Vakharia
Kathan Vakharia

Posted on

Python's Collections Module: namedtuple

Introduction

As it has tuple in it's name, one thing is clear that it will add some superpower🦸‍♀️ to the tuples.

namedtuple is a special type of tuple that has named indices. Ofcourse, they also have normal integer indices as they are tuples anway.

Importing namedtuple

from collections import namedtuple
Enter fullscreen mode Exit fullscreen mode

namedtuple creation

# Step 1: Define namedtuple
# 'typename'=> used when printing an obj & low-lvl stuff
# 'fieldnames'=> list of names of indices
Student = namedtuple(typename='Student',
                     field_names=['fname', 'lname', 'age']
                     )

# Step 2: Create a namedtuple

# explicitly assigning named indices
s1 = Student(fname="Shan", lname="Patel", age=19)

# named indices are inferred
s2 = Student("Kathan", "Vakharia", 19)

print(s1, s2, sep='\n')

"""OUTPUT
Student(fname='Shan', lname='Patel', age=19)
Student(fname='Kathan', lname='Vakharia', age=19)
"""
Enter fullscreen mode Exit fullscreen mode

📑 It is important to note that the identifier you use for defining the namedtuple(Student here) is the one you have to use while instantiating a namedtuple. It has nothing to do with the typename argument-It's just a name for your custom tuple sub-class.

Quoting the python documentation,

collections.namedtuple(typename, field_names,...)
- Returns a new tuple subclass named typename.
We can cross-verify if we want using issubclass function.

>>> issubclass(Student, tuple)
True
# CORRECT WAY
s0 = Student("heet", "vakharia")
print(s0)
"""OUTPUT
blah(fname='heet', lname='vakharia')
""""
Enter fullscreen mode Exit fullscreen mode
# INCORRECT way
Student = namedtuple(typename="blah",
                         field_names=["fname", "lname"]
                        )
s1 = blah("kathan", "vakharia")
"""OUTPUT
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'blah' is not defined
"""
Enter fullscreen mode Exit fullscreen mode

Indexing namedtuples

Indexing namedtuple object is very straight-forward. Here's how you do it,

# way1 : using integer indices
# Same like 'plain-tuples'
print("First element of s1: {}"
      .format(s1[0]))

# way 2: using named indices 'NEW'
print("Element of s2 having named index lname: {}"
      .format(s2.lname))
"""OUTPUT
First element of s1: Shan
Element of s2 having named index lname: Vakharia
"""
Enter fullscreen mode Exit fullscreen mode

As it is a sub-class of tuple, it inherits all the methods and attributs of tuple.
However, there are some interesting methods pertaining to namedtuple. Let's see what are those,

classmethod somenamedtuple._make(iterable)

fields = ["John", "Doe", 34]
print(Student._make(fields))

"""OUTPUT
Student(fname='John', lname='Doe', age=34)
"""
Enter fullscreen mode Exit fullscreen mode

somenamedtuple._asdict()

Returns a new dict which maps field names to their corresponding values,

from collections import namedtuple

Student = namedtuple(typename='Student',
                     field_names=['fname', 'lname', 'age'],
                     )

shan = Student(fname="Shan", lname="Patel", age=19)
kathan = Student("Kathan", "Vakharia", 19)

# namedtuple._asdict() 
print(shan._asdict())
print(kathan._asdict())

"""OUTPUT
{'fname': 'Shan', 'lname': 'Patel', 'age': 19}
{'fname': 'Kathan', 'lname': 'Vakharia', 'age': 19}
"""
Enter fullscreen mode Exit fullscreen mode

somenamedtuple._replace(**kwargs)

Returns a new instance of the named tuple replacing specified fields with new values.

kathan = Student("Kathan", "Vakharia", 19)

# a new tuple will be created with changed fname
kathan_v2 = kathan._replace(fname="Karsh")

print(kathan_v2)

# Old kathan is still unchanged
print(kathan)

"""OUTPUT
Student(fname='Karsh', lname='Vakharia', age=19)
Student(fname='Kathan', lname='Vakharia', age=19)
"""
Enter fullscreen mode Exit fullscreen mode

And that wraps our discussion on namedtuple. I have intentionally left some minor functionalities because they are too trivial :) However, feel free to check out the documentation for that remaining 5% stuff.

Discussion (0)