__getattr__ provides an instance attribute when ordinary lookup cannot find that name. Python first checks the instance’s __dict__; if the name is absent, __getattr__ runs as a fallback. section 9.4.2
Load profile data only when requested
A User class can fetch profile_data lazily. __getattr__ performs the expensive operation only on the first access, stores the result with setattr, and returns the cached value on later accesses. The first request prints '__getattr__ called for profile_data' and '*** Run the expensive operation'; the second returns the same data without repeating the operation. section 9.4.2
Do not initialize the lazy attribute in __init__, even with None, because storing the name in __dict__ prevents __getattr__ from being called. For lazy attributes, properties are usually clearer and more explicit. section 9.4.2 section 9.4.4
