Topics: Immutable classes, namedtuples
Before looking at namedtuples, we should review what a tuple is. In Python, a tuple is a simple data structure that can be used for grouping arbitrary objects. Important to know is that tuples are immutable. That means that once a tuple has been created, it can not be changed anymore. We already used tuples in our Magical Universe. For example, we defined the
pet attribute of the
Pupil class to be a tuple:
pet = ('name', 'type') lissys_pet = ('Ramses', 'cat')
pet tuple has two fields:
type that can be accessed using their integer index. Once we create a tuple like
lissys_pet we can’t change it anymore. For example, running
lissys_pet = 'Twiggles'
TypeError: 'tuple' object does not support item assignment.
As their name suggests, namedtuples are a variation (or rather extension) of plain tuples. In particular, namedtuples allow us to name the fields of the tuple. This makes it much easier to access the individual fields. Also, it makes our code more readable. In the plain tuple example above, we could access the values stored in the tuple only by using integer indices, as
lissys_pet. When having only two fields this is not too bad. But with more than three fields things become messy.
Creating a namedtuple is easy. There are two kinds of namedtuples we can use:
typing.NamedTuple. When using
collections.namedtuple our pet tuple would be defined as follows:
from collections import namedtuple Pet = namedtuple('Pet', ['name, type']) lissys_pet = Pet('Ramses', 'cat')
We can access the fields of the namedtuple using the field names or their indices:
name = lissys_pet # or name = lissys_pet.name
typing.NamedTuple has a slightly different syntax and allows us to specify the type of each field. It also allows us to add methods to the class (although this is possible with
collections.namedtuple, too, it’s a little more complex). Another advantage of the namedtuple classes is that they come with an implementation of the
__repr__ method. So we don’t have to create that ourselves anymore but get a nice string representation of our objects right away (as you can see in the example below).
from typing import NamedTuple class Pet(NamedTuple): name: str type: str lissys_pet = Pet('Ramses', 'cat') print(lissys_pet) >>> Pet(name='Ramses', type='cat')
You can read more about
typing.NamedTuple in the Python docs.
Dark Army class
We don’t want our pupils, professors and ghosts to be immutable. A suitable group of people for an immutable class are the Dark Army members. Why? Because once you become a member of the Dark Army there is now way back. So let’s create a NamedTuple for them!
from typing import NamedTuple class DarkArmyMember(NamedTuple): name: str birthyear: str @property def leader(self) -> 'DarkArmyMember': master_odon = DarkArmyMember('Master Odon', 1971) return master_odon
From now on we can easily create new Dark Army members:
keres = DarkArmyMember('Keres Fulford', 1983) print(keres) >>> DarkArmyMember(name='Keres Fulford', birthyear=1983) print(keres.leader) >>> DarkArmyMember(name='Master Odon', birthyear=1971)