Dunder Methods and Properties
Make your classes feel built in.
Ava would love to write, plus, between two orders, to combine them, and use len on her shop, to count the plants. Python's own types behave like this, and your classes can too. The secret is special methods, with double underscores on each side, called dunder methods. And for safe attributes, there are properties.

- Make objects work with +, len and ==
- Special names with double underscores
- Properties for safe, smart attributes
Common dunder methods
Python calls these special methods behind the scenes. Init creates an object. Str gives the friendly text for print, and repr gives the developer text. Len supports the len function, add supports the plus sign, eq supports double equals, and getitem lets you use square brackets. You rarely call them directly, Python does that for you.
| Method | Triggered by | Used for |
|---|---|---|
| __init__ | Plant(...) | creating the object |
| __str__ | print(obj) | friendly text |
| __repr__ | obj in the REPL | debug text |
| __len__ | len(obj) | size |
| __add__ | a + b | combining |
| __eq__ | a == b | comparison |
| __getitem__ | obj[i] | indexing |
Making an Order feel native
Here, an Order holds a list of prices. Len returns how many items, add combines two orders into a new one, and getitem lets us index into it, which also makes it work in a for loop. Now an order behaves like a built in container, and code using it reads beautifully.
class Order:
def __init__(self, prices):
self.prices = list(prices)
def __len__(self):
return len(self.prices)
def __add__(self, other):
return Order(self.prices + other.prices)
def __getitem__(self, i):
return self.prices[i]
a = Order([10, 5])
b = Order([20])
c = a + b
print(len(c), c[0], sum(c))3 10 35
__repr__ and __eq__
Repr should show how to recreate the object, and appears in lists and in the REPL. The eq method decides when two objects count as equal. Without it, two separate plants with the same data are considered different. Define it, and compare by values, not by identity.
class Plant:
def __init__(self, name, price):
self.name, self.price = name, price
def __repr__(self):
return f"Plant({self.name!r}, {self.price})"
def __eq__(self, other):
return (self.name, self.price) == (other.name, other.price)
a = Plant("fern", 9.5)
b = Plant("fern", 9.5)
print(a)
print([a, b])
print(a == b)Plant('fern', 9.5)
[Plant('fern', 9.5), Plant('fern', 9.5)]
TrueProperties
A property looks like an attribute, but runs code. Mark a method with at property, and callers use it without brackets. A setter, with the name dot setter, runs when a value is assigned, which lets you validate it. Here, a price can never be negative. Users see a simple attribute, while you keep control behind the scenes.
class Plant:
def __init__(self, name, price):
self.name = name
self.price = price
@property
def price(self):
return self._price
@price.setter
def price(self, value):
if value < 0:
raise ValueError("price cannot be negative")
self._price = value
p = Plant("fern", 9.5)
p.price = 12
print(p.price)
try:
p.price = -1
except ValueError as e:
print("Error:", e)12 Error: price cannot be negative
A Basket with len
Your turn. Create a class called Basket, that stores a list of items. Add a len method, so that len of a basket gives the number of items. Create a basket of three items, and print its length. Ready? Here is one solution. Store the list, and return its length from the dunder method.
Create class Basket(items) with __len__, then print len(Basket(["a", "b", "c"])).
Show hint
def __len__(self): return len(self.items)
Show solution
class Basket:
def __init__(self, items):
self.items = list(items)
def __len__(self):
return len(self.items)
print(len(Basket(["fern", "ivy", "rose"])))3
Summary
Brilliant work. Dunder methods make your classes behave like built in types, with len, plus, equals and indexing. Repr and str control how objects print, and properties give you attributes with built in checks. Next, we look at modern tools that remove boilerplate, like data classes, enums and abstract classes.
Key takeaways- Dunder methods: __len__, __add__, __eq__
- __str__ for users, __repr__ for developers
- @property for validated attributes