Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

Lesson 5 of 11

Print one of your own objects and you get something unhelpful:

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

print(Dog("Rex"))

That prints something like <__main__.Dog object at 0x7f8b...> — the type and a memory address. Two dunder methods let you fix that.

__str__ — for humans

__str__ returns the friendly string shown by print() and str().

class Dog:
    def __init__(self, name, breed):
        self.name = name
        self.breed = breed

    def __str__(self):
        return f"{self.name} the {self.breed}"

rex = Dog("Rex", "Labrador")
print(rex)
print(str(rex))
print(f"My dog is {rex}")

It must return a string — printing inside __str__ instead of returning is a common mistake and raises TypeError.

__repr__ — for developers

__repr__ is the unambiguous version, aimed at debugging. It shows up in the REPL, in error messages, and whenever an object sits inside a list.

class Dog:
    def __init__(self, name, breed):
        self.name = name
        self.breed = breed

    def __repr__(self):
        return f"Dog({self.name!r}, {self.breed!r})"

rex = Dog("Rex", "Labrador")
print(repr(rex))
print([rex, rex])

The convention is to make __repr__ look like the code that would recreate the object. !r inside an f-string applies repr() to that value, which is what puts the quotes around the strings.

Notice the second print — a list shows its items using __repr__, never __str__. That's why defining only __str__ still leaves lists looking cryptic.

Which to define

If you define only one, define __repr__. Python falls back to __repr__ when __str__ is missing, so you get sensible output everywhere for the price of one method.

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

    def __repr__(self):
        return f"Dog({self.name!r})"

rex = Dog("Rex")
print(rex)
print([rex])

Define both when a friendly display and a precise debug form should genuinely differ:

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

    def __str__(self):
        return f"${self.amount:.2f}"

    def __repr__(self):
        return f"Money({self.amount})"

m = Money(9.5)
print(m)
print(repr(m))

Try it yourself

Give Book a __str__ for reading and a __repr__ for debugging.

Checkpoint

  • Without these, printing an object shows a memory address.
  • __str__ is the readable form used by print() and str().
  • __repr__ is the unambiguous form used by the REPL, containers, and debugging.
  • Both must return a string, not print one.
  • If you only write one, write __repr__ — __str__ falls back to it.

Questions about this lesson

Log in to ask a question.