A special method is a Python method named by a language-defined convention, usually with two leading and trailing underscores. These methods participate in built-in operations. Because every Python class inherits from object, defining one overrides the inherited implementation. section 8.4
Use special methods to make custom instances behave naturally in common Python operations:
- __init__ initializes an instance when its class is called. section 8.4
- __str__ and __repr__ customize an object's string representations. section 8.4
- __call__ makes an instance callable, allowing function-like syntax. section 10.5.4
- __getattr__ supplies a missing attribute and can defer expensive work until that attribute is requested. section 9.4.2
Turning a decorator object into a callable
A class-based decorator stores a logging closure in _logger and forwards calls through __call__: class TimeLogger: def __init__(self, func): def logger(*args, **kwargs): result = func(*args, **kwargs) print(f"Calling {func.__name__}") return result self._logger = logger def __call__(self, *args, **kwargs): return self._logger(*args, **kwargs) @TimeLogger def calculate_sum(n): return sum(range(n)) calculate_sum(100_000) # output: Calling calculate_sum The decorated name now refers to a TimeLogger instance rather than a function, but __call__ preserves function-like invocation. section 10.5.4
Listing 9.7 Overriding __getattr__ in a class
class User:
def __init__(self, username):
self.username = username
print(f"### User {username} created")
def __getattr__(self, item):
print(f"__getattr__ called for {item}")
if item == "profile_data":
profile_data = self._get_profile_data()
setattr(self, item, profile_data)
return profile_data
def _get_profile_data(self):
# get the data from the server and load it into memory
print("*** Run the expensive operation")
fetched_data = "Extensive data, including thumbnail,
followers, etc."
return fetched_data
Inspect the complete lazy-attribute example: __getattr__ fetches profile_data only when absent, then stores it so later access avoids the expensive operation. section 9.4.2


