Locked learning resources

You must own this product to watch this lesson.

Locked learning resources

You must own this product to watch this lesson.

Customizing Objects

This lesson is from the Real Python video course by Christopher Trudeau.

00:00 In the previous lesson, I got tangential and pedantic about callables. In this lesson, I’ll show you how to override __str__() and __repr__() in your own classes.

00:10 When you define your own class, you are inheriting from Python’s default base class. The base class implements __str__() and __repr__(), but you can override these methods for your own purposes.

00:23 In fact, I’d recommend it. The default implementations are beauty-impaired. When you do override these, remember the basic idea outlined at the beginning of this course: __str__() is for users and __repr__() is for programmers.

00:37 Back to the REPL. I’m going to start by declaring a class to show you the default implementations of __str__() and __repr__().

00:54 The Book class has one attribute, a title, which I set in the initializer. Let’s instantiate a book.

01:04 Ooh, scary clown. And now I’ll evaluate the object. See what I mean? Not the prettiest response. In fact, not only is it a little ugly, it also violates the recommendation.

01:16 I can’t eval() this and get a copy of the book object. Ugly or not, see eye of the beholder, there is some useful information here. The __main__ is because I’m in the REPL.

01:28 That’s the name of the module the class is defined in, and if you define a class in the REPL, the module name is __main__. Next, it has the name of the class and a hexadecimal value.

01:41 The number in hex is the value of the memory location. Actually, if you convert it to decimal, you’ll find it’s the same value returned by the id() function that I used in the previous lesson.

01:52 Let’s stringify our book and the result is the same. The base implementation of __str__() and __repr__() return the same thing. Time to override a special method. Let’s go to the movies.

02:16 So far, this is similar to the book. Now let’s override the __str__() method.

02:26 __str__() takes no additional arguments, but it is a method on a class, so it does need .self.

02:36 And whatever you return from the method is what gets used when you convert it to a string. You pretty much better return a string otherwise, things might go badly later.

02:45 Using an f-string inside the method is pretty common as you typically want a template containing some of the attributes from the object. Let me create a movie.

02:56 Many of Mr. King’s books became movies. In fact, according to a random factoid site on the internet, 34 of his books became movies. That puts him third. He’s beat out by Agatha Christie, who has 48 and William Shakespeare at a whopping 1,121.

03:14 The factoid page I stole this info off of is a few years old, so the numbers might not be accurate. And this is a tangent in a Python course not a modern cinema class.

03:25 Let’s look at our movie object. Same ugly repr(), because I didn’t overload it, but when you convert it to a string, the overridden __str__() gets invoked.

03:38 Let’s try this again with a new class, this time overriding __repr__(). Seeing the pattern yet? Now for the repr(),

03:51 like with __str__(), it takes no additional arguments

04:00 and the best practice is to return a string that could be evaluated to create a new class. Note my use of the !r in the f-string, so the output will have the value surrounded in quotes.

04:12 Let’s instantiate a song.

04:17 Little David Lee Roth, and there it is in the repr() caused by the REPL evaluating it. If I copy and paste that, also_song is a new version.

04:36 Hmm, did you expect that? The examples I showed before were all literals and Python knows how to compare two literals. I haven’t told Python how to compare two Song objects and because I haven’t, it defaults to checking if they’re the same object, which they are not.

04:57 The comparison mechanism itself is done through a dunder method. I am not going to cover it here, but you could override __eq__() and change this behavior so comparison worked the way you might expect it to.

05:10 Alright, time for one more.

05:26 When I overrode __repr__() in Song, I hardcoded the name of the class. If you change the name of the class, you have to remember to change the string in __repr__().

05:37 Instead, you can do what I’ve done here, which is use the .self.__class__ attribute to get at the current object’s class and that class’s .__name__ attribute to get its name.

05:49 Now, if I renamed the Poem class to Sonnet, I wouldn’t have to edit my code; it would be correct. Let me create a poem and evaluate it and __repr__() still works.

06:04 Python 3.7 introduced the idea of a data class. This is to make classes that contain mostly attributes simpler to write. They are a shortcut for writing certain kinds of classes.

06:15 One of the advantages of a data class is it has more useful dunder display methods. To declare a data class, you decorate a regular class. A data class decorator is in the dataclasses module.

06:33 Now that I’ve imported it, I use it to decorate my new class.

06:42 This declarative form says that the Game class has an attribute named title that is a string. This shortcut means I don’t need a __init__() method. Not a big deal, it doesn’t actually save that much code when you’ve only got one thing, but if you have a lot of attributes, this is significantly cleaner.

06:59 And of course, the whole reason I brought it up is a useful default repr(), which actually is compliant with the recommendation. It also provides a default str().

07:14 That’s the core part of the course. Last up, I’ll summarize and point you at other courses you might find interesting.

You must own this product to join the conversation.