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.
00:12
The 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.
00:30
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 __slots__
value.
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.
00:54
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.
01:05
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.
01:21
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 namedtuple
class.
01:34
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.
01:41
This is a common convention in Python. With the base person ready, I create the new PersonTuple
class by extending the base person.
01:52
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.
02:21
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.
02:33
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 …
03:07
and the date
object as person tuple’s .birth
attribute expects a date.
03:18
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 .__repr__()
.
03:29
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.