Named Tuples in Python
As I read the great book Python Tricks by Dan Bader I learned about named tuples and was pretty amazed about this. Named tuples can help you to make your code more structured and readable in certain circumstances. They can be used as an alternative to dicts or unstructured tuples. Here is how they work.
1>>> from collections import namedtuple
2>>> Dog = namedtuple('Dog', 'breed color character') # same as the following
3>>> Dog = namedtuple('Dog', ['breed', 'color', 'character'])
4>>> rocky = Dog('pitbull', 'brown', 'excited')
5>>> rocky.breed
6'pitbull'
7>>> rocky.color
8'brown'
9>>> rocky.character
10'excited'
11>>> rocky[1]
12'brown'
13>>> rocky
14Dog(breed='pitbull', color='brown', character='excited')
The first argument of namedtuple is Dog, this is the type name as namedtuple cannot know the name of the variable. The variables of this class are either defined as a space separated single string or as an array of strings. You can then define a variable as Dog
and then access the single variables as you would do it with every other class. Or even using an index as you would expect froma tuple.
If you forgot to assign a variable you get the following error.
1>>> sunny = Dog('pitbull', 'brown')
2Traceback (most recent call last):
3 File "<stdin>", line 1, in <module>
4TypeError: __new__() missing 1 required positional argument: 'character'
As with regular tuples they are immutable.
1>>> rocky.breed = 'bulldog'
2Traceback (most recent call last):
3 File "<stdin>", line 1, in <module>
4AttributeError: can't set attribute
You can even add methods as the named tuples are build upon classes.
1>>> class DogWithSound(Dog):
2... def bark(self):
3... if self.breed == 'pitbull':
4... print('WOOF')
5... elif self.breed == 'jack russel terrier':
6... print('woof woof woof')
7... else:
8... print('bark')
9...
10>>> princess = DogWithSound('pitbull', 'brown', 'lovely')
11>>> princess.bark()
12WOOF
A Python convention is that methods or variables starting with an _ underscore should be handled as private. However, this does not count for named tuples. They have a few integrated help methods, starting with an underscore but which belong to the public interface. This was done to prevent naming conflicts with the tuple fields the user defines. In the following a few help methods are shown.
1>>> princess._asdict()
2{'breed': 'pitbull', 'color': 'brown', 'character': 'lovely'}
3>>> princess._replace(character='playful')
4DogWithSound(breed='pitbull', color='brown', character='playful')
5>>> Dog._make(['golden retriever', 'golden', 'happy'])
6Dog(breed='golden retriever', color='golden', character='happy')
The method _asdict
returns a dict representation of the named tuple. _replace
creates flat copy of the tupel and returns the copy with the corresponding field changed. And _make
creates a new object based on an iteratable object.