Theme: Python allows you to dynamically intercept attribute lookups. This enables the creation of elegant, declarative APIs (like Django ORM or Pydantic) by transforming dictionary keys into dot-notation object attributes.
| Concept | Explanation |
|---|---|
__getattr__ |
Intercepts attribute lookups ONLY when the attribute does not exist. |
__getattribute__ |
Intercepts EVERY attribute lookup unconditionally. Highly dangerous. |
@property |
Allows you to execute a function when a user accesses a basic attribute, enforcing the Uniform Access Principle. |
__new__ |
The true object constructor. Executes before __init__ and physically returns the instance. |
examples.py— Building a recursive JSON wrapper (FrozenJSON) from scratch using__getattr__.exercises.py— The infamous__getattr__infinite recursion loop, and why you must sanitize Python keywords (likeclass) in APIs.mini_project.py— A robust API client wrapper that overrides__new__to dynamically return either a list or a parsed object depending on the raw JSON type.benchmarks.py— Proves that metaprogramming adds a 2x–3x CPU overhead compared to accessing raw dictionary keys.notes.md— The mechanical difference between__getattr__and__getattribute__.pitfalls.md— The severe architectural mistake of hiding heavy I/O operations (like database queries) behind simple@propertylookups.interview_questions.md— L3 to L6 interview prep.architecture_notes.md— Howfunctools.cached_propertyhacks the CPython__dict__sequence to achieve O(1) performance.
# Rule 1: Always use __getattr__, NEVER use __getattribute__ unless you are an expert.
# __getattribute__ requires `super().__getattribute__(name)` to avoid infinite loops.
# Rule 2: If a JSON response contains a Python keyword, append an underscore.
if keyword.iskeyword(key):
key += '_' # 'class' becomes 'class_'
# Rule 3: Use @functools.cached_property for expensive dynamically calculated attributes.
@cached_property
def query_results(self):
return run_large_db_query() # Only runs on the very first access!Reference: Fluent Python 2nd ed., Chapter 22 — pages 863–905