1. Classes and dunders (double underscores)

Use dunder methods when they improve how objects behave. In particular, override __str__ to provide a printer-friendly representation of an object.

Special methods let your objects participate in Python’s built-in protocols instead of requiring callers to remember custom helper methods. That usually produces code that feels more native at the call site and concentrates representation logic inside the type that owns it.

1.1. Don’t do this

1class Student():
2    def __init__(self, first_name, last_name):
3        self.first_name = first_name
4        self.last_name = last_name
5
6student = Student('John', 'Doe')
7
8print(student)

1.2. Do this

 1class Student():
 2    def __init__(self, first_name, last_name):
 3        self.first_name = first_name
 4        self.last_name = last_name
 5
 6    def __str__(self):
 7        return f'{self.first_name} {self.last_name}'
 8
 9student = Student('John', 'Doe')
10
11print(student)