The __str__() method returns the string representation of an object. If you have ever used the builtin str() function, you have also indirectly used the __str__()  method. This is because  the builtin str() function actually calls __str__() method on the target object. So when we are casting another type to string using the str() function, we are just simply calling the __str__() method on the respective object albeit indirectly.

The __str__() method belongs to a category of methods known as the dunder(double underscore) or magic methods. It is meant to  provide a human-friendly representation of an object and this makes it a useful tool for displaying,  debugging and logging purposes..

Every object in Python, whether builtin or user-defined always have this method defined by default. This in turn makes it possible to call the str() function with literally any Python object.

ExampleEdit & Run
#Calling the __str__ nmethod of a list
L = [1, 2, 3, 4]
print(L.__str__()) #Same as print(str(L))

#Calling the __str__ method of a dictionary
D = {1: "One", 2: "Two", 3: "Three", 4: "Four"}
print(D.__str__())

#Calling the __str__ method of a function
def add(a, b):
    return a + b

print(add.__str__()) #Same as str(add)
Output:
[1, 2, 3, 4]{1: 'One', 2: 'Two', 3: 'Three', 4: 'Four'}<function add at 0x7f2d791cc900>[Finished in 0.010584762087091804s]

Overriding the __str__() methods for user-defined objects

With user-defined objects, the __str__()  method, by default returns a string providing general information such as the class the object belongs, and its memory address. 

ExampleEdit & Run
class Example:
    pass

e = Example()
print(e)
Output:
<__main__.Example object at 0x7f2ccaa8a090>[Finished in 0.010154885007068515s]

We can override this behavior by implementing the  __str__()  method on the class definition and making it return a more meaningful value.

ExampleEdit & Run
class Example:
    def __str__(self):
       return "This is an example"

e = Example()
print(str(e))
Output:
This is an example[Finished in 0.010346736991778016s]

A more practical example: 

ExampleEdit & Run
class Person:
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __str__(self):
      return "%s, %s"%(self.name, self.age)

p1 = Person("John", 30)
p2 = Person("Mary", 26)
p3 = Person("Juliet", 28)

print(str(p1))
print(str(p2))
print(str(p3))
Output:
John, 30Mary, 26Juliet, 28[Finished in 0.010359151056036353s]

As you have seen above, defining the __str__ method in a class makes it possible to represent instances more specifically and  in a more user-friendly format.

Like all other instance methods, the __str__ method must include the self parameter in the definition. The method should not take any additional required parameter apart from self,  attempting this will result in a TypeError being raised.

The __str__() method should always return a string object, otherwise a TypeError will be raised if you call the str() function.

ExampleEdit & Run
class Example:
    def __str__(self):
        return 1

e = Example()
str(e)
Output:
Traceback (most recent call last):  File "<string>", line 6, in <module>TypeError: __str__ returned non-string (type int)[Finished in 0.010372546035796404s]

Conclusion:

  • The __str__() method returns the string representation of an object
  • The builtin str() function literally calls the __str__() method of the specified object.
  • All Python objects have the __str__() method defined by default
  • We can override the default __str__() method in a class definition
  • The __str__() method should not include a required parameter apart from self.
  • The __str__() method must strictly return a string object, otherwise a TypeError is raised.