Extending namedtuple Classes
00:00 In the previous lesson, I emceed the big showdown: named tuples against other Python data classes. In this lesson, I’ll show you how to extend a named tuple and why you might do that.
namedtuple() factory returns a class. You can inherit from that class to create other classes. Before data classes, this was a common thing to do. Now it’s not as important, but given there are memory differences between named tuples and data classes, you might still want to use this idea.
The reason to extend a named tuple is to make it more like a plain old data object. You can add methods like you would with any other class. To maintain your slim memory profile, there is one thing you have to do, which is set the
00:45 Python classes normally have a dictionary associated with their underlying implementation. When you change something in the object, it is that dictionary that gets updated.
When you specify the
__slots__ value in a class, you are telling Python that you’re not interested in updating the attributes in the class. This means the dictionary can be optimized away.
Clever use of
__slots__ can lead to faster attribute access and less memory use. For our subclass of named tuple, I’m going to be setting
__slots__ to ensure that I keep the memory advantage of the parent class. Let’s go look at some code.
In this code, I’m once again creating a class that represents a person, but this time I’m doing it by subclassing a named tuple. To subclass a named tuple, first, you need a
I have called mine
_BasePerson and have named it with a leading underscore to indicate that it isn’t supposed to be used outside the module.
This is a common convention in Python. With the base person ready, I create the new
PersonTuple class by extending the base person.
As I mentioned before, this is the
__slots__ value. By setting it to
empty, I’m indicating to Python that I don’t need a dictionary associated with this class. In a regular class, I’d include the names of the attributes that I was exposing in here, but the
namedtuple parent class will handle that, so a blank tuple is good enough.
02:11 This is a bit tricky, and in real code, it really should have a comment explaining what is going on. The rest of the class contains the methods I wanted to add.
I’m being a bad boy here and having
.__repr__() return a string that isn’t very REPL friendly. Best practice with this method is to return something that can be copy and pasted into the REPL to create an equivalent object.
I’m mucking with this because I’m going to show it off in the REPL. You probably should be better behaved than I am. And finally, I’ve added a property called
age that calculates how old the person tuple is by finding the difference between today and their birthdate.
02:49 There are probably edge cases with this calculation, given leap years and things, but it’s good enough to show off what I’m talking about. Let’s see if this works.
03:00 Importing my new class …
date object as person tuple’s
.birth attribute expects a date.
And here I’ve created
Juanita, born on December 22, 1999. Since I’m in the REPL, the method called when I display something is
This would be my rebel string that ignores best practices. And of course, it contains Juanita’s age, so the
age property was called to print this string. Except for the
__slots__ thing, this is like any inheriting from any other class, and even if you forgot the
__slots__ thing, you’d still get a class that works.
03:48 It just won’t be as performant as a named tuple.
03:55 That’s pretty much it for named tuples. In the last lesson, I’ll summarize the course and point you at some further investigation.
Become a Member to join the conversation.