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

Custom Data Types

When you pass an object to print(), it converts it to a string using the str() function. You can create a __str__() method on your custom objects to change what is output:

Language: Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f'Person({self.name})'

Here’s what you’ll get:

Language: Python
>>> from person import Person
>>> john = Person('John Cleese', 80)
>>> print(john)
Person(John Cleese)

The __str__() method is meant to output a human-readable version of your object. There is also a __repr__() method, which is meant for a Python representation of the object. There is a repr() function that corresponds to the str() function. If you define your __repr__() properly, then eval() can be called on its result to create a new object:

Locked learning resources

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

Unlock This Lesson

Already a member? Sign-In

Locked learning resources

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

Unlock This Lesson

Already a member? Sign-In

00:00 In the previous lesson, I showed you how to use print() to write to a file. In this one, I’m going to show you how to customize your classes to affect what gets printed when your object gets passed into the print() function.

00:12 The print() function tends to be one you would learn early on in your Python journey, and this lesson is related to objects in Python. In case you haven’t done any object-oriented Python yet, let me give you the 30-second introduction.

00:25 A class is a way of grouping data and code related to that data together. You declare a class with Python’s class keyword. The class acts like a template which you can then use to create an object, which is the actual data you’re trying to represent.

00:40 Classes and objects can have both data attributes and methods associated with them. A method is a function that is associated with a class. Don’t ask me why there’s a separate name for it. There just is.

00:52 Let’s look at a short example. Say I wanted to represent a person in my code. A person would have data like their name, and I might want to perform operations on the person through methods.

01:02 I declare a person using the class keyword. Python objects have special methods denoted by double underscores. The __init__() method is what gets called when you’re creating a new instance of Person.

01:16 Here, I’ve set it to take an argument, the person’s name. But before that, there’s self. self is a reference to the object itself.

01:24 That way, when you’re inside of any method, you can access the object instance being manipulated. You can assign attributes to an object using dot notation. This is kind of like keys in a dictionary in that the object keeps track of the things associated with it.

01:40 This line says to take the object instance, that’s self being passed in, and copy the name argument passed into the method. This allows you to get at the name elsewhere in the object.

01:51 Here, I’ve defined a method on the class. The only argument it takes is the object instance, so nothing additional will get passed in. What my method does is reverse the name string and return it.

02:03 That square brackets double colon minus one is a little trick you can use to reverse a sequence. Let me show you what it would look like to use this class in the REPL.

02:12 You instantiate a new instance by calling the class like it’s a function. Whatever is passed into the class when it’s created gets sent to the __init__() method.

02:23 So my string "Bob" here gets passed in as the name argument above. You can access the attribute of an object with dot notation. My "Bob" string got stored away on the name attribute inside of the call to __init__().

02:38 So I can now access that attribute elsewhere when I have a reference to the object.

02:45 Calling a method on the object is like calling a function, but with dot notation to get at the method. Note that both when calling __init__() and our backwards() method, the self gets left off.

02:56 You don’t need it in the calling just in the declaration.

02:59 Python fills that in for you based on the object that you’re using. If you’ve never done object-oriented coding in Python, this lesson might be a bit much for you.

03:07 My whirlwind tour only gives you a taste. There are full courses on the subject if you want to learn more.

03:14 print() converts its arguments to strings using str(). You’ve seen this in previous lessons. The str() method looks for two methods defined on a class to help it to know how to convert to a string.

03:27 The first is __str__(). The second is __repr__(). Just a quick note, because double underscore is so hard to say, a lot of programmers, or at least the cool kids, will refer to this as dunder.

03:41 So the two methods you can define on a class are __str__() and __repr__(). If the str() method can’t find __str__() or __repr__(), it just uses a built-in default. The guidelines state __str__() should be used for human-readable content.

04:00 By contrast, __repr__() is used to include far more detailed information. In fact, the Python documentation says that you should be able to pass __repr__() to the eval() method and have it create the object itself.

04:15 I’ll show you what this looks like inside of a REPL. For instance, let’s say you have a simple class Person that defines a name and an age and stores them on the object.

04:27 If I have this inside of a file called person and I import it, I can create an object with John Cleese with an age of 80. Now, because I haven’t defined __str__(),

04:40 print() uses the default method. The ugly number at the end there is an object identifier. That’s actually specific to the CPython implementation.

04:50 If you’re using a different kind of Python, that string might actually look different. Now, because this is so ugly, let’s add a __str__() method to our class. Now, reprint john

05:06 and str() is now calling __str__(), which then is a pretty formatted string. And this is a much more useful piece of information to have show up when you print() your object. Now I’ve modified the Person object, adding a __repr__().

05:23 Once again, I can create this person.

05:26 No difference from before.

05:28 Just like str(), there’s a built-in method called repr(). If I called repr() on john, it shows what will come back from the __repr__() of the person object.

05:39 If you look at this closely, you’ll notice that what is returning from __repr__() in this case is valid Python code.

05:47 This is different from what’s in __str__().

05:52 I can eval() the repr() value and create a new object. If you haven’t seen eval() before, it’s a built-in function that takes a string, treats it as Python code and attempts to run it. Generally, eval() is considered dangerous, particularly if you’re taking input from users.

06:10 They would be able to change your code on the fly. But this case shows you how you can actually take something from the __repr__() result and evaluate it, creating the new object.

06:21 If I ask Python what the type is, it’s a class of a person. If I ask for the id(), this is the same as the id() that the default str() spits out. I get one number on the original john object and a different number on the new john2 object, which shows you the eval() has used the string to create a brand new object.

06:43 Let’s look at this one more time. This time there’s a User object taking a username and password. And I’ve defined both a __str__() and a __repr__() method.

06:55 Like before, import the user,

06:59 create a User object.

07:04 Calling str() on it will show you the username. Something that’s a little tricky though is that some container objects will call the repr() directly rather than the str() method.

07:14 If I make the same call but on a list of users instead, the repr() gets called. The str() method of a list calls the repr() method of each of the items inside of the list. In this particular case, that would be exposing the password, which isn’t a good idea.

07:34 print is one of the more obvious changes between Python 2 and Python 3. In the next lesson, I’ll talk about these differences and how you can take advantage of the new features in Python 3.

Avatar image for akolal

akolal on Jan. 7, 2021

I am having a real tough time seeing a dark blue font against a black background in the repl. Perhaps it is just me. But the choice in other videos were great. Please consider changing it.

Avatar image for Christopher Trudeau

Christopher Trudeau RP Team on Jan. 7, 2021

Thanks for the feedback akolal. Can I just confirm that it is the keywords like “print” or “<stdin>” that are too dark? Or are there others colours that are problematic as well?

Become a Member to join the conversation.