AI Hints
Home›Python Tutorial›Object-Oriented Python
Python · Lesson 18 of 49

Dunder Methods and Properties

Make your classes feel built in.

⏱ 2 min read▶ Video at 58:20🎓 Free
Watch this lesson in the Python courseWatch on YouTube ↗Full Python course

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.

Dunder Methods and Properties
From the video: Dunder Methods and 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.

MethodTriggered byUsed for
__init__Plant(...)creating the object
__str__print(obj)friendly text
__repr__obj in the REPLdebug text
__len__len(obj)size
__add__a + bcombining
__eq__a == bcomparison
__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.

dunder.pypython
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))
Output
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.

repr_eq.pypython
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)
Output
Plant('fern', 9.5)
[Plant('fern', 9.5), Plant('fern', 9.5)]
True

Properties

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.

property.pypython
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)
Output
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.

✍️ Exercise: A Basket with len

Create class Basket(items) with __len__, then print len(Basket(["a", "b", "c"])).

Show hint

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

Show solution
basket.pypython
class Basket:
    def __init__(self, items):
        self.items = list(items)

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

print(len(Basket(["fern", "ivy", "rose"])))
Output
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
Next up: Dataclasses, Enums, ABCs — less boilerplate, safer design