__str__ vs __repr__ in Python

Aditya Raj Oct 10, 2023
  1. the str() Function in Python
  2. the __str__() Method in Python
  3. the repr() Function in Python
  4. the __repr__() Method in Python
  5. __str__() vs __repr__() in Python
  6. Conclusion
__str__ vs __repr__ in Python

In Python, we usually convert any object into a string using the str() function. Similarly, we can get the string representation of an object using the repr() function. For the str() and the repr() to produce output, the object that is passed to these functions must have an implementation of the __str__() method and the __repr__() method, respectively.

Often, the developers are confused between the functionalities and use cases of these methods. In the tutorial, we are going to discuss how the str() function and the repr() function work and how the __str__() method and the __repr__() method affect the behavior of an object.

the str() Function in Python

The str() function is used to obtain the string representation of an object. It takes an object as an input argument and returns its string representation. For instance, we can obtain the string representation of a floating-point number, as shown in the following example.

myNum = 123.456
myStr = str(myNum)
print("The number is:", myNum)
print("The string is:", myStr)

Output:

The number is: 123.456
The string is: 123.456

Similarly, we can convert other objects of built-in data types such as integers, lists, sets, tuples, etc into their respective string representations using the str() function as shown below.

myNum = 123
myList = [1, 2, 3, 4, 5]
mySet = {1, 2, 3, 4, 5}
myStr1 = str(myNum)
myStr2 = str(myList)
myStr3 = str(mySet)

print("The number is:", myNum)
print("The string is:", myStr1)
print("The list is:", myList)
print("The string is:", myStr2)
print("The set is:", mySet)
print("The string is:", myStr3)

Output:

The number is: 123
The string is: 123
The list is: [1, 2, 3, 4, 5]
The string is: [1, 2, 3, 4, 5]
The set is: {1, 2, 3, 4, 5}
The string is: {1, 2, 3, 4, 5}

However, the output isn’t understandable when we pass an object defined using a custom class definition. To observe this, let us define a Student class with the attributes name and age.

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age


student1 = Student("Aditya", 23)
myStr = str(student1)
print("The string representation of student object is:")
print(myStr)

Output:

The string representation of student object is:
<__main__.Student object at 0x7f6016100070>

Here, you can see that the function’s output isn’t as understandable as it appeared when we converted an object defined using the built-in data structures. Why does this happen?

When we pass an object to the str() function, the __str__() method defined in the class definition is invoked. The __str__() method returns the object’s string representation. The str() function then returns the same string. However, there is no __str__() method when we define a custom class. Due to this, the output of the str() function is not very understandable.

the __str__() Method in Python

According to our requirements, we can implement the __str__() method in any class definition. The only restriction here is that the method must return a string value. For example, we can implement the __str__() method for the Student class, as shown below.

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        myString = "Name: {} , Age: {}".format(self.name, self.age)
        return myString

After implementing the __str__() method, when we pass any Student object to the str() function, it returns the same string returned by the __str__() method. The following example shows how it works.

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        myString = "Name: {} , Age: {}".format(self.name, self.age)
        return myString


student1 = Student("Aditya", 23)
myStr = str(student1)
print("The string representation of student object is:")
print(myStr)

Output:

The string representation of student object is:
Name: Aditya , Age: 23

You can implement the __str__() method in any manner. For instance, we can define the __str__() method of the Student class in an alternative way as shown below.

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        myString = "Name of student is: {} ,{} is {} years old".format(
            self.name, self.name, self.age
        )
        return myString


student1 = Student("Aditya", 23)
myStr = str(student1)
print("The string representation of student object is:")
print(myStr)

Output:

The string representation of student object is:
Name of student is: Aditya ,Aditya is 23 years old

How we implement the __str__() method doesn’t affect the program’s execution. The output of the __str__() method is used solely for showing output to the user.

the repr() Function in Python

The repr() function is used to obtain the formal string representation of any object. It also takes an object as input and returns the string representation of an object as shown below.

myNum = 123
myList = [1, 2, 3, 4, 5]
mySet = {1, 2, 3, 4, 5}
myStr1 = repr(myNum)
myStr2 = repr(myList)
myStr3 = repr(mySet)

print("The number is:", myNum)
print("The string is:", myStr1)
print("The list is:", myList)
print("The string is:", myStr2)
print("The set is:", mySet)
print("The string is:", myStr3)

Output:

The number is: 123
The string is: 123
The list is: [1, 2, 3, 4, 5]
The string is: [1, 2, 3, 4, 5]
The set is: {1, 2, 3, 4, 5}
The string is: {1, 2, 3, 4, 5}

You can observe that the output of the repr() function is almost identical to the output of the str() function. However, the working of both methods is entirely different. When we pass any object to the str() function, the __str__() method is invoked. On the other hand, when we pass any object to the repr() function, the __repr__() method is invoked. The following example shows how it works.

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        myString = "Name of student is: {} ,{} is {} years old".format(
            self.name, self.name, self.age
        )
        return myString


student1 = Student("Aditya", 23)
myStr1 = str(student1)
myStr2 = repr(student1)
print("The string representation of student object is:")
print(myStr1)
print("The output of repr() is:")
print(myStr2)

Output:

The string representation of student object is:
Name of student is: Aditya ,Aditya is 23 years old
The output of repr() is:
<__main__.Student object at 0x7f6410b78070>

We have defined the Student class with the __str__() method here. You can observe that the outputs are different if we pass an instance of the Student class to the str() function and the repr() function.

The str() function returns the output returned by the __str__() method while the repr() function returns the output returned by the __repr__() method. If we don’t implement the __str__() method, the str() function also returns the output from the __repr__() method.

the __repr__() Method in Python

The __repr__() method returns the canonical representation of an object in python. The __repr__() method is implemented for all the objects in python irrespective of whether they are instances of built-in or custom classes. You can understand the definition of the __repr__() method for objects defined using custom classes as follows.

def __repr__(self):
    return "<{0}.{1} object at {2}>".format(
        self.__module__, type(self).__name__, hex(id(self))
    )

Here, self.__module denotes the module in which the current object is created, type(self).__name__ denotes the name of the class, and hex(id(self)) denotes the identity of the object in hexadecimal format. The following example shows how it works.

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        myString = "Name of student is: {} ,{} is {} years old".format(
            self.name, self.name, self.age
        )
        return myString


student1 = Student("Aditya", 23)
myStr = student1.__repr__()
print("The output of __repr__() is:")
print(myStr)

Output:

The output of __repr__() is:
<__main__.Student object at 0x7feb92cc8070>

Here, you can see that the output of the __repr__() method is similar to the schema defined in the method definition. The output shows that the object has been defined in the __main__ module and is of the Student class. The output also shows the identity of the object.

You should always avoid overriding the __repr__() method. This is because the __repr__() method is used to create a canonical string representation of the object, with the help of which we can re-instantiate the same object.

However, if we override the __repr__() method, we will not be able to create the object from its string representation using the eval() function.
As we have discussed the basics of the __str__() method and the __repr__() method, let us list some of the differences between the two methods.

__str__() vs __repr__() in Python

The __str__() method returns the user-readable string form of an object that the developer can customize. However, the __repr__() method returns a canonical string representation of the string. In some cases, the string returned by __str__() method might be the same as the string returned by the __repr__() method. You can observe this in the case of numbers.

However, When we take a string or an object using a custom class definition, the string returned by the __repr__() method is different from the string returned by the __str__() method. The following example shows how it works.

myStr = "Aditya"
myStr1 = myStr.__repr__()
myStr2 = myStr.__str__()
print("The string is:", myStr)
print("The output from the __repr__() method is:", myStr1)
print("The output from the __str__() method is:", myStr2)

Output:

The string is: Aditya
The output from the __repr__() method is: 'Aditya'
The output from the __str__() method is: Aditya

Here, you can observe that the string returned by the __str__() method is Aditya. On the other hand, the __repr__() method returns the canonical string representation 'Aditya'.

  • When we pass the string returned by the __repr__() method to the eval() function, it returns the object. On the other hand, when we pass the string returned by the __str__() method to the eval() function, it may or may not return the python object. For instance, look at the following example.
myNum = 1234
myNum1 = myNum.__repr__()
myNum2 = myNum.__str__()
print("The number is:", myNum)
print("The output from the __repr__() method is:", myNum1)
print("The output from the __str__() method is:", myNum2)
output1 = eval(myNum1)
print(output1)
output2 = eval(myNum2)
print(output2)

Output:

The number is: 1234
The output from the __repr__() method is: 1234
The output from the __str__() method is: 1234
1234
1234

Here, you can observe that we can obtain an integer object from a string representation of the integer obtained using the __str__() method and the __repr__() method. Now, look at the following example.

myStr = "Aditya"
myStr1 = myStr.__repr__()
myStr2 = myStr.__str__()
print("The string is:", myStr)
print("The output from the __repr__() method is:", myStr1)
print("The output from the __str__() method is:", myStr2)
output1 = eval(myStr1)
print(output1)
output2 = eval(myStr2)
print(output2)

Output:

The string is: Aditya
The output from the __repr__() method is: 'Aditya'
The output from the __str__() method is: Aditya
Aditya
/usr/lib/python3/dist-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (3.0.4) doesn't match a supported version!
  warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "
Traceback (most recent call last):
  File "/home/aditya1117/PycharmProjects/pythonProject/webscraping.py", line 9, in <module>
    output2 = eval(myStr2)
  File "<string>", line 1, in <module>
NameError: name 'Aditya' is not defined

You can see that we can create a string object from the string returned by the __repr__() method. However, when we try the create the string object using the string returned by the __str__() method, the program runs into the NameError exception.

  • You can override the __str__() method and implement it according to your need. However, you should not override the __repr__() method.
  • The __repr__() method is mainly used by developers while debugging. On the other hand, the __str__() method is used to obtain a textual representation of an object that the user can understand.
  • The __repr__() method is invoked to produce the output when we type the variable’s name or the object in the interactive python console. On the other hand, the __str__() method is invoked when we pass the variable to the print() function or the str() function.
  • If the class definition does not contain the __str__() method, the __repr__() method is invoked by the python interpreter when we pass the object to the str() function.
  • When we pass a container object to the print() function, the __repr__() method of the elements of the container object is printed, irrespective of whether we have implemented the __str__() method in the class definition of the elements or not.

Conclusion

In this article, we have discussed the working of the str() function, __str__() method, repr() function, and the __repr__() method. We also discussed the difference between the uses of the __str__() method and the __repr__() method.

Although the outputs of both methods are similar, there are distinct differences that make the __repr__() method and the __str__() method very different from each other. I suggest you use the __repr__() method to obtain the string representation of the objects in the cases when you need to re-instantiate the object using the string representation.

On the other hand, you should use the __str__() method to produce a human-readable representation of the object that has no use in the program apart from informing the user.

Author: Aditya Raj
Aditya Raj avatar Aditya Raj avatar

Aditya Raj is a highly skilled technical professional with a background in IT and business, holding an Integrated B.Tech (IT) and MBA (IT) from the Indian Institute of Information Technology Allahabad. With a solid foundation in data analytics, programming languages (C, Java, Python), and software environments, Aditya has excelled in various roles. He has significant experience as a Technical Content Writer for Python on multiple platforms and has interned in data analytics at Apollo Clinics. His projects demonstrate a keen interest in cutting-edge technology and problem-solving, showcasing his proficiency in areas like data mining and software development. Aditya's achievements include securing a top position in a project demonstration competition and gaining certifications in Python, SQL, and digital marketing fundamentals.

GitHub

Related Article - Python String