Dunder Methods & Operator Overloading
You'll learn to
- -Implement `__str__` and `__repr__` to control how an object prints and debugs
- -Implement `__eq__` and `__len__` to make custom objects comparable and sizeable
- -Understand `__lt__` and how it enables sorting custom objects
By default, printing an instance of your own class produces an unhelpful message like `<__main__.Stack object at 0x7f8b2c0a1d90>`. Dunder ("double underscore") methods let you plug your class into Python's built-in behaviors - printing, equality, `len()`, sorting - so your objects behave as naturally as the built-in types you have been using all course. This matters immediately: several early Forge Algorithm Lab levels ask you to build a class, and a clean `__repr__` is often the difference between a five-second debugging session and a confusing one.
__str__ and __repr__
`__str__` controls what `print(obj)` and `str(obj)` show - a readable, human-facing description. `__repr__` controls what you see in a debugger, a REPL, or inside a list/dict of objects - it should ideally be unambiguous enough to help you debug, and by convention often looks like code that could recreate the object.
If you only implement one of the two, implement `__repr__` - Python falls back to `__repr__` for `print()` if `__str__` is missing, but not the other way around. This is exactly what you want when debugging a failing Forge Algorithm Lab submission: a good `__repr__` lets you `print()` your data structure mid-algorithm and immediately see its state.
__eq__: Custom Equality
By default, `==` on two instances of your class checks identity (are they the exact same object in memory), the same as `is`. `__eq__` lets you define what "equal" means for your class - typically, that all the meaningful attributes match.
__len__ and __lt__
`__len__` lets `len(obj)` work on your class - useful for any custom container (a stack, a queue, a hash map - exactly the kind of classes the Forge Algorithm Lab asks you to build). `__lt__` ("less than") defines what `<` means between two instances, and once it exists, `sorted()` and `.sort()` can order your objects automatically.
- -`__str__`: human-readable display, used by `print()` and `str()`.
- -`__repr__`: unambiguous debug representation, used by the REPL, debuggers, and inside collections.
- -`__eq__`: defines `==` between two instances (attribute-by-attribute comparison instead of identity).
- -`__len__`: makes `len(obj)` work - essential for any custom container type.
- -`__lt__`: defines `<`, which is all `sorted()` and `.sort()` need to order a list of your objects.
These are called "dunder" methods because their names start and end with double underscores. Python calls them automatically in response to built-in syntax (`print()`, `==`, `len()`, `sorted()`) - you almost never call them directly yourself.
What is the main practical difference between `__str__` and `__repr__`?