Image of __repr__ in Python

ADVERTISEMENT

Table of Contents

Introduction

Object-oriented programming (OOP) is an extremely important coding concept. It revolves around the idea of programmatic "objects" that have different properties and behaviors, much like objects in the real world. Classes are used to define the structure (attributes and methods) of objects, and objects are generated (instantiated) from each class.

Python is an object-oriented programming language. In fact, almost everything in Python - for example a list or a string - is considered to be an object. Since Python is an OOP language, classes can be defined in Python, and you can define object behavior by using methods. As we'll see, a method is basically a function that is included within a class.

Some classes have built-in "special" methods associated with them, which can be identified by 2 underscores before and after the method name, like __repr__.

In this article, we will look at the special method __repr__ in Python, and understand how it is used for defining objects.

Overview of Classes in Python

Before with dive into special methods in Python, it's important to have a basic understanding of classes.

So, first, let's define some terminology:

  • Class - A class in Python is defined with the class statement. You can think of it as a blueprint for creating a specific type of object.
  • Attribute - An attribute is a variable that describes a property of objects created from the class they are a part of.
  • Method - A method is a function inside a class, which defines a behavior of objects created from the class.
  • Instance - An instance is a resulting object that is created from a class, that contains the properties (attributes) and methods (behaviors) of the class.

Let's look at an example:

class Thing:
    attr1 = 0
    attr2 = 1
    
    def getAttr1(self):
        return self.attr1

Here, you have a Thing class with two attributes attr1 and attr2 and a method getAttr1. The method has a single argument self, which refers to the instance once it's created, and all methods in a class should always have the self as their first argument. You can create instances from the class by calling the class much like you would a function, and assigning to a variable:

instance1 = Thing()
instance2 = Thing()

We can call instance methods like so:

>>> instance1.getAttr1()
0

As we mentioned, Python classes offer "special methods", which allow us to implement different kinds of behaviors with classes.

What are special methods in Python?

Special methods allow you to use Python's built-in functionality with the objects you create. Special methods are can easily be identified as their names start end with double underscores, like __specialMethodName__().

Let's look at the most popular special method __init__(), which is called automatically when an instance is created. This special method is called a constructor. Most class definitions you'll see will contain the __init__() method.

class Thing2:
    def __init__(self, a):
        print("Initializing instance...")
        self.a = a
    
    def get_a(self):
        return self.a

In this example, you have the __init__() method, which prints a statement when an instance is created. You can also see that there is an argument a for __init__(). Then there's the line self.a = a, which assigns the property a to the object, so you can use this variable in other methods. Finally, you have a get_a() method that simply returns the value of the class's a property.

Let's see how this works:

>>> inst1 = Thing2(5)
Initializing instance...
>>> inst1.get_a()
5

First, you can see that when creating an instance, you can give the class arguments (like you do for functions), which you defined in __init__() and the "Initializing instance..." output proves that __init__() ran. When you use get_a() you get back the value of the argument you specified when creating the instance.

Now let's look at a real-world example of how you can use built-in functions with the objects by defining a Book class with the attributes name and the total number of pages, totalPages. First, let's define a class Book and an instance of the class:

class Book:
    def __init__(self, name, totalPages):
        self.name = name
        self.totalPages = totalPages    

The length of a book would be the number of pages it has, but if you wanted to use the len() function with our object you get an error:

>>> book0 = Book("To Kill a Mockingbird", 200)
>>> len(book0)
TypeError                                 Traceback (most recent call last)
/var/folders/yk/wp7m5ypn4v3cyfpv27m4d37c0000gn/T/ipykernel_7143/3077360197.py in <module>
----> 1 len(book0)

TypeError: object of type 'Book' has no len()

To make this work, you can add the __len__() special method in your class definition:

class newBook:
    def __init__(self, name, totalPages):
        self.name = name
        self.totalPages = totalPages
    
    def __len__(self):
        return self.totalPages

You can now use the len() method to with the class instance supplied as an argument:

>>> book1 = newBook("To Kill a Mockingbird", 200)
>>> len(book1)
200

When using the built-in len() function to find the length of any object, Python will search the object for the special method called __len__(), which should return the property or value to get the length of.

This is only the tip of the iceberg in terms of classes and special methods. Classes are an extremely powerful tool that can do so much more and are used throughout the industry. To learn more about classes you can read through Python's official documentation on Classes.

Overview of __repr__() method

Before we touch on the "special method" version, we should note that repr() is actually a function similar to print() in Python. It can be used outside of classes just like any other built-in function. The difference is that string will typically print out the contents of a string or other Python object in a human readable format. On the other hand, the repr() function prints out the "string representation" of an object, which usually includes quotes surrounding it. For example:

>>> a = ['dog', 'cat', 'cow']

>>> print(a)
['dog', 'cat', 'cow']

>>> repr(a)
"['dog', 'cat', 'cow']"

Note that the output is very similar, but repr() shows an additional set of quotes containing the list values.

The __repr__() special method is used within classes to return the string representation of an object, which is returned when instances from that class are supplied as arguments to print() or repr().

Normally, if you were to print an object without a __repr__() method defined in the class you would get something like this:

<__main__.Book object at 0x7f8155c7ff10>

While that default output does identify the object type as Book, it doesn't tell us much about the book.

Here is an example of using the special method __repr__() within a class to customize the output of print() and repr() when supplied with an instance of the class:

class Book:
    def __init__(self, name, totalPages, author):
        self.name = name
        self.totalPages = totalPages
        self.author = author
    
    def __len__(self):
        return self.totalPages
    
    def __repr__(self):
        return f'Book(name={self.name}, totalPages={self.totalPages}, author={self.author})'

Now with __repr__(), if we print() (or repr()) the object we can choose to return useful information about the Book, including its object type, name, page number, author, and the variables name associated with each property:

>>> book1 = Book("To Kill a Mockingbird", 200, "Harper Lee")
>>> print(book1)
Book(name=To Kill a Mockingbird, totalPages=200, author=Harper Lee)

Now, this output tells you the class of the object, the name of the book, author, and total pages. Note that this output is still in a bit of a technical format, which we'll explain in the next section.

__repr__() vs __str__()

There is another special method __str__() which is very similar to __repr__(). In fact, it's hard to tell how they are even different. Let's dig into this.

The idea behind the __str__() special method is to return human-readable information on the object, while __repr__() is for returning the string representation that we discussed before. In the previous example, you saw what __repr__() should return for the book1 object.

Now let's implement __str__() method into that example:

class Book:
    def __init__(self, name, totalPages, author):
        self.name = name
        self.totalPages = totalPages
        self.author = author
    
    def __len__(self):
        return self.totalPages

    def __repr__(self):
        return f'Book(name={self.name}, totalPages={self.totalPages}, author={self.author})'

    def __str__(self):
        return f'The name of the book is "{self.name}" by {self.author} and it has {self.totalPages} pages'
    
book1 = Book("To Kill a Mockingbird", 200, "Harper Lee")
>>> book1 = Book("To Kill a Mockingbird", 200, "Harper Lee")

>>> print(book1)
The name of the book is "To Kill a Mockingbird" by Harper Lee and it has 200 pages

>>> repr(book1)
Book(name=To Kill a Mockingbird, totalPages=200, author=Harper Lee)

When you use __repr__() or __str__(), the corresponding special method will run when the object instance is specified in the print() or repr() function.

Summary

In this article, you looked at the special method __repr__() in Python and learned how it helps us in constructing objects.

First, you did an overview of classes in Python. Then you learned what special methods are and looked at different examples showing real-world use cases of special methods. Next, you went over the special method __repr__() by implementing it into a class. Finally, you looked at the very similar __str__ special method to compare and contrast functionality of different special methods.

Next Steps

If you're interested in learning more about the basics of coding, programming, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.

Final Notes