Magic Methods
Master Python's powerful magic methods (dunder methods) and understand how the Python data model works under the hood. Learn to create custom classes that behave like built-in types, implement operator overloading, and build professional-grade objects.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
🔥 1. What Are Magic Methods?
Magic methods are methods Python calls automatically when certain operations happen.
Operation
Magic Method
len(obj)
__len__
obj + other
__add__
obj[i]
__getitem__
for x in obj
__iter__
str(obj)
__str__
with obj:
__enter__, __exit__
obj()
__call__
They let you define how your objects behave in every situation.
⚙️ 2. Object Construction (Creation & Initialization)
- ✔ custom immutable types
- ✔ singleton patterns
- ✔ building objects from cached pools
🧱 3. Representation Methods
These control how an object looks when printed or displayed.
__repr__ — official representation (for developers)
Used for f-strings, formatting currencies, dates, metrics.
🔢 4. Numeric Magic Methods (Act Like Numbers!)
Implementing these turns objects into custom numeric types:
Also available: Subtraction, Multiplication, Division, Modulo, Power, Negation
- ✔ game engines
- ✔ simulation math
- ✔ ML tensor wrappers (PyTorch does this heavily)
🧠 5. Comparisons (Sorting, Ordering, Equality)
- __eq__ — equals
- __ne__ — not equal
- __lt__ — less than
- __gt__ — greater than
- ✔ leaderboard systems
- ✔ sorting objects
- ✔ priority queues
- ✔ ranking algorithms
📦 6. Container Protocol (Behaving Like Lists & Dicts)
🔄 7. Iterable Protocol (for...in Loops)
- __iter__ — return an iterator
- __next__ — steps through values
- ✔ custom data streams
- ✔ tokenizers
- ✔ ML data loaders
- ✔ generators
🧩 8. Callable Objects (Pretend to Be Functions)
- ✔ ML models (PyTorch layers implement __call__)
- ✔ function wrappers
- ✔ on-the-fly factories
- ✔ middleware
🔐 9. Attribute Access Control
- __getattr__ — fallback for missing attributes
- __getattribute__ — intercept ALL attribute access
- __setattr__ — intercept setting attributes
- __delattr__ — intercept deletion
- ✔ lazy loading
- ✔ proxies (database lazy models in Django)
- ✔ dynamic API clients
- ✔ configuration wrappers
🧱 10. Boolean Value
- if statements
- conditional checks
🧊 11. Context Managers
- ✔ file handling
- ✔ database sessions
- ✔ locking systems
- ✔ resource guards
🧱 12. Copy & Serialization Hooks
- __deepcopy__
- __getstate__
- __setstate__
- how objects are serialized
- custom caching behavior
- saving/loading ML models
- multiprocessing transfers
🔥 13. Operator Overloading (Make Objects Behave Like Built-ins)
Python lets you define how your objects react to operators.
- __add__(self, other) — +
- __sub__(self, other) — -
- __mul__(self, other) — *
- __truediv__(self, other) — /
- __floordiv__(self, other) — //
- __mod__(self, other) — %
- __pow__(self, other) — **
- ✔ physics simulations
- ✔ ML tensors (PyTorch / TensorFlow)
- ✔ financial modeling
- ✔ vector graphics engines
🧱 14. Rich Comparisons — Smarter Sorting & Ranking
If you must support ordering, implement the following:
- __lt__(self, other) — <
- __le__(self, other) — <=
- __gt__(self, other) — >
- __ge__(self, other) — >=
- __eq__(self, other) — ==
- __ne__(self, other) — !=
🧩 15. Sequence Protocol (Full Custom List Behavior)
- __len__(self)
- __getitem__(self, index)
- __setitem__(self, index, value)
- __delitem__(self, index)
- __contains__(self, item)
🧠 16. Iterable vs Iterator (Clear Distinction)
- for loops depend on it
- generator pipelines rely on it
- async systems use async iterators
- ML dataloaders use custom iterables
🧱 17. Custom Iterators (Full Control of Data Streams)
- ✔ streaming input
- ✔ chunked database queries
- ✔ on-the-fly data generation
- ✔ scraper crawls
- ✔ batching ML data
🔐 18. Attribute Access Magic
Python gives complete control over attribute access.
- __getattr__(self, name) — Occurs when attribute is missing
- __getattribute__(self, name) — Intercepts every attribute lookup
- __setattr__(self, name, value) — Intercepts setting attributes
- __delattr__(self, name) — Intercepts deletion
🧩 19. Emulating Functions With __call__
- neural network layers
- preprocessing pipelines
- middleware wrappers
- job schedulers
- configurable callbacks
🧱 20. Context Manager Magic
- __enter__(self)
- __exit__(self, exc_type, exc, tb)
🔥 21. Descriptors — The Hidden Power Behind @property
A descriptor is any object defining one or more of:
- __get__(self, instance, owner)
- __set__(self, instance, value)
- __delete__(self, instance)
🧬 22. Properties Built on Top of Descriptors
property is just a wrapper around descriptors.
⚡ 23. Slots — Memory-Efficient Objects
- ✔ lower memory
- ✔ faster attribute access
- ✔ prevents accidental attributes
⚡ 24. Understanding the Python Object Lifecycle
- Allocation → __new__
- Initialization → __init__
- Destruction → __del__
🔥 25. Metaclasses — The Most Advanced Python Feature
Classes create objects. Metaclasses create classes.
What metaclasses are used for IN REAL SYSTEMS
- ✔ Django ORM
- ✔ SQLAlchemy Models
- ✔ Pydantic / FastAPI Models
- ✔ TensorFlow Layers
- ✔ Enum internals
- ✔ Plugin systems
- ✔ Service registries
🧩 26. Class Decorators vs Metaclasses
Class decorators modify the class after it's created:
Metaclasses modify the class while being created.
- Class decorator → simple modification
- Metaclass → structural modification
🧠 27. Emulating Containers (Full Custom Collections)
🧱 28. Making Your Objects Hashable
For objects to be used as dictionary keys OR in sets:
🔍 29. Overriding Truthiness & Boolean Behavior
🧬 30. Controlling String Representations
⚙️ 31-34. Advanced Topics
- Dynamic Attribute Computation - Using __getattr__ for lazy loading
- Proxy Objects - Forwarding magic methods
- Custom Number Types - Money, Temperature classes
- Full Domain Models - Complete custom types
🎓 35. Final Summary — You Now Understand the Entire Python Data Model
By mastering this lesson, you now understand:
- ✔ operator overloading
- ✔ full comparison system
- ✔ container emulation
- ✔ iterator/iterable protocols
- ✔ attribute access magic
- ✔ callable classes
- ✔ context manager internals
- ✔ descriptor protocol
- ✔ property internals
- ✔ slots memory optimization
- ✔ object lifecycle
- ✔ metaclass architecture
- ✔ custom domain-specific types
- ✔ proxy patterns
- ✔ advanced debugging behaviors
You now write Python the way framework authors, not beginners, write it.
This knowledge places you firmly at the top 1% of Python engineers.
📋 Quick Reference — Magic Methods
Method
Triggered by
__init__(self)
Object creation: MyClass()
__repr__(self)
repr() and interactive shell display
__len__(self)
__getitem__(self, key)
obj[key] indexing
__enter__ / __exit__
with obj: context manager
You now control how your objects respond to built-in Python operations — the same protocol powering NumPy, pandas, and SQLAlchemy.
Up next: Operator Overloading — make your custom types support +, -, <, and other operators naturally.
Practice quiz
Which magic method is called when you do len(obj)?
- __size__
- __count__
- __len__
- __length__
Answer: __len__. Python calls __len__ to implement len(obj).
Which magic method implements obj + other?
- __add__
- __plus__
- __sum__
- __concat__
Answer: __add__. __add__ defines behavior for the + operator.
What does __repr__ provide?
- A user-friendly display for end users
- The length of the object
- A boolean value
- An official, developer-facing representation of the object
Answer: An official, developer-facing representation of the object. __repr__ is the official representation aimed at developers; __str__ is the user-friendly one.
Which two magic methods make an object work in a for...in loop as its own iterator?
- __loop__ and __step__
- __iter__ and __next__
- __getitem__ and __len__
- __enter__ and __exit__
Answer: __iter__ and __next__. An iterator implements __iter__ (returns self) and __next__ (yields values, raising StopIteration to end).
Which magic method lets an instance be called like a function, e.g. obj(10)?
- __call__
- __invoke__
- __run__
- __exec__
Answer: __call__. __call__ makes an instance callable, so obj(10) runs obj.__call__(10).
Which pair of magic methods implements the 'with obj:' context manager protocol?
- __open__ and __close__
- __start__ and __stop__
- __enter__ and __exit__
- __begin__ and __end__
Answer: __enter__ and __exit__. Context managers implement __enter__ (on entry) and __exit__ (on exit).
Which magic method controls the result of len() AND is part of the sequence protocol alongside __getitem__?
- __count__
- __len__
- __items__
- __size__
Answer: __len__. __len__ controls len(obj) and, with __getitem__, forms the core sequence protocol.
To use your objects as dictionary keys or in sets, which methods must you implement?
- __key__ and __set__
- __dict__ and __getitem__
- __index__ and __len__
- __hash__ and __eq__
Answer: __hash__ and __eq__. Hashable objects need __hash__ and a matching __eq__ so they behave correctly in dicts and sets.
Which method is the fallback called only when a normal attribute lookup fails?
- __getattribute__
- __getattr__
- __getitem__
- __get__
Answer: __getattr__. __getattr__ is the fallback for missing attributes; __getattribute__ intercepts EVERY attribute access.
What is a metaclass?
- A class with only static methods
- A class that cannot be instantiated
- The class of a class — it creates classes (default is type)
- A copy of a class
Answer: The class of a class — it creates classes (default is type). A metaclass is the class of a class; classes create objects, metaclasses create classes (default metaclass is type).