DEV Community

Deepika Pusala
Deepika Pusala

Posted on

Week 04 - Task 1.2: dunder/magic methods (__init__, __repr__, __eq__, __len__, __add__, etc.)

Python Dunder Methods, Demystified πŸͺ„

__init__, __repr__, __add__... they look scary with all those underscores. But once you get the one idea behind them, they stop being magic and start being obvious.


πŸ”€ What Does "Dunder" Even Mean?

Dunder = Double UNDERscore.

__init__
 ↑     ↑
 double  double
 underscore underscore
Enter fullscreen mode Exit fullscreen mode

So dunder methods are just methods whose names start and end with __. You'll also hear them called magic methods or special methods β€” all three names mean the same thing.

Examples: __init__, __repr__, __eq__, __len__, __add__


πŸ’‘ Why Do They Exist?

Python already knows what to do with its built-in types:

print(10 + 20)        # 30
print(len("hello"))   # 5
Enter fullscreen mode Exit fullscreen mode

But now make your own class:

class Money:
    def __init__(self, amount):
        self.amount = amount

m1 = Money(100)
m2 = Money(200)
print(m1 + m2)   # πŸ’₯ Error!
Enter fullscreen mode Exit fullscreen mode

Python has no idea what + should mean for two Money objects. Dunder methods are how you teach Python what to do. Define __add__, and suddenly + makes sense for your class too.

The big idea: dunder methods let your custom objects behave like Python's built-in ones.


βš™οΈ Are They Automatic?

Yes β€” but you still write them yourself. You just don't call them directly.

You write Python actually calls
a + b a.__add__(b)
len(a) a.__len__()
a == b a.__eq__(b)
print(a) uses a.__repr__()

You define the dunder method once inside your class. From then on, Python quietly routes the normal syntax to it behind the scenes.

🧠 The translation trick: whenever you see a + b, mentally read it as a.__add__(b). Do this for every operator and dunder methods stop feeling magical.


πŸ™‹ A Quick Word on self

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

s1 = Student("Deepika")
Enter fullscreen mode Exit fullscreen mode

When Python runs s1 = Student("Deepika"), it's really doing s1.__init__("Deepika") internally β€” and inside that method, self is s1. So self.name = name simply means s1.name = "Deepika".


🧰 The Core Dunder Methods

__init__ β€” set up the object

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
Enter fullscreen mode Exit fullscreen mode

Runs automatically when you create an object, to set its starting values.

⚠️ Common myth: "Every class must have __init__." False β€” it's optional. class Student: pass is perfectly valid Python.

__repr__ β€” give it a readable identity

Without it:

print(s)
# <__main__.Student object at 0x000001...>
Enter fullscreen mode Exit fullscreen mode

With it:

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

    def __repr__(self):
        return f"Student(name='{self.name}', age={self.age})"

print(s)
# Student(name='Deepika', age=21)
Enter fullscreen mode Exit fullscreen mode

Mostly used for clean debugging/logging output.

__eq__ β€” define what "equal" means

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

    def __eq__(self, other):
        return self.name == other.name

s1 = Student("Deepika")
s2 = Student("Deepika")
print(s1 == s2)   # True
Enter fullscreen mode Exit fullscreen mode

__len__ β€” teach len() about your object

class Team:
    def __init__(self, members):
        self.members = members

    def __len__(self):
        return len(self.members)

team = Team(["A", "B", "C"])
print(len(team))   # 3
Enter fullscreen mode Exit fullscreen mode

__add__ β€” define what + means

class Money:
    def __init__(self, amount):
        self.amount = amount

    def __add__(self, other):
        return Money(self.amount + other.amount)

m3 = Money(100) + Money(200)
print(m3.amount)   # 300
Enter fullscreen mode Exit fullscreen mode

🧩 Putting It All Together

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

    def __repr__(self):
        return f"Student(name='{self.name}', marks={self.marks})"

    def __eq__(self, other):
        return self.marks == other.marks

    def __len__(self):
        return len(self.marks)

    def __add__(self, other):
        return Student(self.name + " & " + other.name,
                        self.marks + other.marks)

s1 = Student("Deepika", [90, 95])
s2 = Student("Koushik", [85, 92])

print(s1)          # __repr__  β†’ Student(name='Deepika', marks=[90, 95])
print(len(s1))     # __len__   β†’ 2
print(s1 == s2)    # __eq__    β†’ False
s3 = s1 + s2        # __add__
Enter fullscreen mode Exit fullscreen mode

🚨 Don't Confuse __main__ with __init__

if __name__ == "__main__":
    print("Program started")
Enter fullscreen mode Exit fullscreen mode

__name__ is a special variable and "__main__" is just a special value it can hold β€” it's not a dunder method. Easy to mix up because both have double underscores, but they're unrelated concepts.


🏒 Where This Shows Up in Real Code

Scenario Dunder used Why
Combining prices in a cart __add__ product1 + product2 reads naturally
Financial apps (Money, Invoice) __add__ total = m1 + m2 instead of manual math
Shopping cart item count __len__ len(cart) instead of len(cart.items)
Debugging a User object __repr__ print(user) β†’ User(id=101, name='Deepika') instead of a memory address

This isn't just interview trivia β€” it's how real Python libraries (like datetime, pandas, or pathlib) make objects feel native to the language.


🎯 Cheat-Sheet Answers

Question Short Answer
What are dunder methods? Special methods with double-underscore names that define how your objects respond to built-in Python operations
Do we call them directly? Usually no β€” normal syntax (+, len(), ==) triggers them automatically
Do all classes need __init__? No, it's optional β€” only needed to initialize attributes
Why called "magic methods"? Because Python invokes them behind the scenes, without an explicit call

🧠 One Picture to Remember

              YOUR OBJECT
                   β”‚
        "How should I behave?"
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       ↓           ↓            ↓
      +            ==          len()
       ↓           ↓            ↓
  __add__       __eq__       __len__

object created  β†’ __init__
object printed  β†’ __repr__
Enter fullscreen mode Exit fullscreen mode

Golden rule: Dunder methods are the mechanism Python uses to let your custom objects participate naturally in its built-in operations.

Top comments (0)