Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Customizing Objects

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.

Become a Member to join the conversation.