What is the difference between __str__ and __repr__, and what are dunder methods for?
Dunder (double underscore) methods let your classes participate in Python's built-in syntax. Defining __len__ makes len(obj) work; __eq__ makes == work; __iter__ makes the object usable in a for loop; __enter__ and __exit__ make it a context manager.
__repr__ is for developers. It should be unambiguous and, ideally, valid Python that would recreate the object. It is what you see in the REPL, in a debugger, and inside a printed list.
__str__ is for users. It should be readable. It is what print() and str() use.
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
def __str__(self):
return f"({self.x}, {self.y})"The practical rule: always define __repr__; define __str__ only when a friendlier form is genuinely useful. If __str__ is missing, Python falls back to __repr__ — but not the other way round, which is why a class with only __str__ still shows as an unhelpful memory address inside a list.
Note: @dataclass generates a sensible __repr__, __eq__, and __init__ for you, and is usually the right answer for a plain data-holding class.





