SyntaxStudy
Sign Up
Python __str__, __repr__ & Magic Methods
Python Intermediate 10 min read

__str__, __repr__ & Magic Methods

__str__, __repr__ & Magic Methods

Magic (dunder) methods let you define how objects behave with built-in Python operations like printing, arithmetic, and comparison.

__str__ vs __repr__

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        # For developers — should be unambiguous
        return f"Vector({self.x!r}, {self.y!r})"

    def __str__(self):
        # For end users — readable
        return f"({self.x}, {self.y})"

v = Vector(3, 4)
print(v)        # (3, 4)  — uses __str__
print(repr(v))  # Vector(3, 4) — uses __repr__

Arithmetic Magic Methods

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    def __abs__(self):
        return (self.x**2 + self.y**2) ** 0.5

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)    # (4, 6)
print(v1 * 3)     # (3, 6)
print(abs(v2))    # 5.0

Comparison & Container

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __len__(self):
        return 2   # a 2D vector has 2 components

    def __getitem__(self, index):
        return (self.x, self.y)[index]
Example
class Fraction:
    def __init__(self, num, den):
        from math import gcd
        g = gcd(abs(num), abs(den))
        self.num = num // g
        self.den = den // g

    def __repr__(self):
        return f"Fraction({self.num}, {self.den})"

    def __str__(self):
        return f"{self.num}/{self.den}"

    def __add__(self, other):
        return Fraction(self.num * other.den + other.num * self.den, self.den * other.den)

    def __eq__(self, other):
        return self.num == other.num and self.den == other.den

a = Fraction(1, 2)
b = Fraction(1, 3)
print(a + b)       # 5/6
print(repr(a))     # Fraction(1, 2)
print(a == Fraction(2, 4))  # True
Pro Tip

Implement __repr__ first — Python falls back to it when __str__ is missing. A good __repr__ should produce a string that recreates the object if passed to eval().