Displaying Object Information
00:00 In the previous lesson, I gave an overview of the course. In this lesson, I’ll introduce you to the two special methods for displaying an object. Everything in Python is an object.
00:12 Sorry about that, just a little Easter egg for those who listen to the Real Python podcast. When you want to display an object, Python provides two different ways of doing that.
00:22 Both mechanisms use special methods. Special methods are methods on a class that begin and end with double underscores, and they’re also known as dunder —that’s short for double underscore—or magic methods.
00:35 The cool kids say dunder, so in an effort to fool you into believing I’m one of you, I’m going to be sticking with that for this course.
00:44 Dunder methods typically aren’t called directly. They can be, they’re methods like anything else, but more often it’s from some other action on an object.
00:53 For example, there are dunder methods for when you compare two objects, dunder methods for accessing parts of an object and what you’re here to learn about, the dunder methods for displaying an object.
01:05 Not only is everything in Python an object, I should get that looked at, it seems to be an involuntary reflex. All objects in Python inherit from a base object.
01:16 In older versions of Python, you had to be explicit about this, but in Python 3, anything you create as a class inherits the default implementation automatically. The base class contains default implementations of dunder methods amongst other things, which is why conversion to a string works even if you haven’t explicitly defined the behavior yourself.
01:39
The first of the two displayed dunder methods I’m going to be talking about is __str__
. This is used as an informal description of an object and it’s what gets called when you convert an object to a string. That includes things like printing the object or using it inside of an f-string.
01:57
You can convert an object directly to a string by using the str()
callable. This essentially casts the object to a string, and under the covers it invokes the __str__
special method.
02:09
The intent of the special method is to display user-friendly information about the object. __str__
’s close sibling is __repr__
.
02:18 The intent here is to return a more detailed version of an object’s description. When an entry in the REPL returns an object, this is the special method that gets invoked to display the response.
02:30
Like with the str()
callable, there is also a repr()
callable and the intent of this one is to display information for programmers.
02:39
The Python documentation recommends that the output from repr()
should contain the information needed to create a new version of the object.
02:48
In fact, it goes so far as to suggest that calling the built-in eval()
function on the result should return an instance with the same attributes.
02:56 Let’s head into the REPL and play with these special methods. To show you how the dunder display methods get called on an object, I’m going to need an object.
03:06
I’m going to use the datetime
object, which contains a date and time. Let me import the module and a little confusingly the name of the datetime
class is the same as the module.
03:18 The class has a class factory method, which returns a new instance containing the current date and time. Let me call it,
03:29
and the today
variable contains a datetime
object. By evaluating the variable in the REPL —that’s fancy talk for typing it in—you get back a repr()
version, more on that in a second.
03:42 But first, let’s print this out.
03:45
Notice how the result of the print()
call is different from the result when I evaluated the variable. print()
is converting the object to a string, and the datetime
’s string conversion method returns the ISO 8601 date format.
03:59 That’s the only format programmers should use, and quite frankly, the whole planet should adopt. The idea that you have to know what country you’re in to decide if 01/02/2024 is January 2nd or February 1st is a little nutty, and besides, it’s a number.
04:15 Big things in numbers go to the left. Tangent, I apologize. I live in a country where two formats are used and our immediate neighbors to the south use a third date format.
04:25
Tends to mean I’ve been bit by this weirdness. Where was I? Oh yeah. Strings. print()
converts the object to a string by using the str()
callable.
04:34 That’s a built-in function, which you can invoke yourself.
04:39
Notice the subtle difference between the print()
and the str()
output. The str()
callable returns a string, which in the REPL gets displayed as a thing in quotes. Single quotes, even. I’m looking at you Black reformatter.
04:53
Alright, that’s two tangents in 20 seconds. I better stop it now. While print()
is invoking the str()
callable, its return value is nothing.
05:01
The reason you see something in the REPL is because print()
has a side effect of printing content, so the information below the prompt with a print()
is from print()
itself rather than the REPL showing the return value of print()
.
05:16
That’s why with print()
, there’s no quotes, but when calling str()
, there is. Remember how I said the result from repr()
should be enough information to construct a new object?
05:28
I’m going to create a new variable by pasting in the output from the today
value in the REPL. Now that I’ve done that, also_today
contains a new datetime
object with the same attributes as today
.
05:41 I can prove that by comparing them.
05:46 See, they’re the same, whereas if I convert it to a string,
05:56
the comparison fails. today
is a datetime
object, and although metaphysically not_today
has the same information in it, not_today
is a string.
06:07
You can see this by using Python’s built-in type()
callable, it displays information about an object or class.
06:15
today
is an instance of a datetime
class from the datetime
module,
06:21
whereas not_today
is an instance of a string.
06:25
To go along with the str()
callable, there is a repr()
callable, which in fact is what the REPL is using to display the result of an evaluation.
06:36
Again, repr()
returns a string just like the str()
callable does. This can be a little confusing. Evaluating something in the REPL or printing it out in the REPL shows the contents of the string while calling the str()
callable or the repr()
callable results in a string and a string in the REPL has quotes around it.
06:56
This is only messy inside the REPL. When you’re using the str()
and repr()
callables in your code, you’ll always be getting a string back, which you can then do something with.
07:06
The built-in eval()
takes a string and attempts to evaluate it as Python. Generally speaking, this is something you should avoid. You want to be very careful when executing the contents of arbitrary strings, especially if the user gave them to you.
07:20
They could have put anything in there. That said, let’s do it. I’m now going to evaluate the response from our repr()
call.
07:30
The datetime
class’s repr()
is well-behaved. The string it returns contains the information needed in the right format so that if you evaluate it, what you get back is a new copy of the same code.
07:42 I’ll prove the sameness. Let me do it again and store it away.
07:50 And now I’ll compare it,
07:54
and you’ve come full circle. today
was turned into a repr()
string, that string got evaluated, and the new object is equivalent to the original.
08:03
So far, you’ve seen different results from __str__
and __repr__
. That isn’t always the case though. Next up, I’ll show you when they are the same.
Become a Member to join the conversation.