Pebellslearn by building
0%
RoadmapMatrixCatalogSandboxSign in
Objects  ›  Capstone Project

Dunder Methods

Methods 15 minMaking your own type behave like one of Python's
You're building a piece ofA bank account that can't go wrong
This piece — __repr__ / __eq__: Prints readably and compares sensibly, like a built-in type.
Scenario Printing an account currently shows <__main__.Account object at 0x...>. Nobody can read that in a log at 3am.
Your task
Give Account a __repr__ returning "Account(owner='Ada', balance=100)" and an __eq__ treating two accounts as equal when owner and balance both match. Write describe(owner, balance) returning the repr string. Example: describe("Ada", 100) → "Account(owner='Ada', balance=100)".

Dunder Methods

Your account works. Now try to look at one.

python

<__main__.Account object at 0x7f...>. That is the least useful sentence in programming, and it's what every log line, every debugger and every error message will show you until you fix it.

Dunder methods — double-underscore names like __repr__ — are how a type plugs into Python itself. They're the difference between a class you built and a type that feels native.


__repr__: be readable

python

The convention: make it look like the code that would recreate the object. When something goes wrong at 3am, that string is what you'll be reading.

Note the second line — putting objects in a list shows their __repr__, not __str__. That's why __repr__ is the one to write first.

It must return a string, not print one:

broken — fix itTypeError

Run it and read the error. Then make it print Account(Ada) exactly once.

__eq__: say what equal means

By default, two objects are equal only when they're the same object:

What does this print?
class Money:
    def __init__(self, amount):
        self.amount = amount

print(Money(5) == Money(5))

Define what equality means for your type and it behaves the way people expect:

python

__len__ and __add__: hook the built-ins

len(x) isn't a method call — it's Python asking x for its __len__. The same goes for + and __add__.

python

Notice __add__ returns a new Playlist rather than modifying self. That matches how + behaves for numbers and strings — a + b should never change a — and breaking that expectation is worse than not implementing + at all.

Step through the addition and watch a third object appear:

step through it
1class Playlist:
2 def __init__(self, tracks):
3 self.tracks = tracks
4 
5 def __add__(self, other):
6 return Playlist(self.tracks + other.tracks)
7 
8a = Playlist(["one"])
9b = Playlist(["two"])
10c = a + b
11print(len(a.tracks), len(b.tracks), len(c.tracks))

a and b are untouched. c is new.


Which ones are worth it

You will not implement most of them. In practice:

  • __repr__ — always. It costs one line and pays back every time you debug.
  • __eq__ — when your type is a value (money, a point, a date) rather than an identity (a user session, a connection).
  • __len__, __iter__, __getitem__ — when your type genuinely wraps a collection, so len(), for and [0] mean the obvious thing.
  • __add__ and friends — rarely, and only when the operator has one obvious meaning. Clever operators are how libraries become unreadable.

🎯 Your turn

Give Account a __repr__ returning "Account(owner='Ada', balance=100)" and an __eq__ treating two accounts as equal when owner and balance match. Then write describe(owner, balance) returning the repr string:

  • describe("Ada", 100)"Account(owner='Ada', balance=100)"
  • describe("Sam", 0)"Account(owner='Sam', balance=0)"

Hint — watch the quotes: the owner is quoted inside the string, the balance isn't. An f-string handles both.

Then press ▶ Run and hit ✓ Check. This one closes the section. ✅

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upPrint something readable

Define Point(x, y) with a __repr__ returning "Point(1, 2)". Write show(x, y) returning repr(p).

dunder__repr__
DrillEqual by value

Define Money(amount) with __eq__ comparing amounts. Write same(a, b) returning whether two Money objects are equal.

dunder__eq__
BuildMake len() work

Define Playlist holding a list of tracks with __len__. Write how_many(tracks) returning len(playlist).

dunder__len__
BossMake + mean something

Define Money(amount) with __add__ returning a NEW Money holding the sum. Write total(a, b) returning the .amount of Money(a) + Money(b).

dunder__add__
CapstoneAn account that feels built-in

Define Account(owner, balance) holding a list history of amounts, with deposit(amount), __len__ (number of transactions), __eq__ (same owner and balance) and __repr__. Write audit(owner, amounts) returning {"repr": ..., "count": ..., "same_as_fresh": ...} — the repr, len(acct), and whether it equals a fresh account with the same owner and final balance.

dunder__repr____eq____len__
describe.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
describe(owner, balance) → strBuild an Account and return its repr.
try:
returned
Press Run to execute your code.
Press Check to run the tests for this lesson.