liveBook · Manning

Special method

As explained in Python How-To

A special method is a Python method with a language-defined naming convention and protocol role, commonly using double underscores to control built-in object behavior.

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

How Python How-To covers it

How deep it goes
Explains overriding with concrete __str__, __repr__, __call__, and __getattr__ examples, while noting that attribute resolution is simplified.
Examples
Demonstrates custom representations, a class-based timing decorator, boilerplate data classes, and cached profile-data lookup.
What it assumes
Assumes basic classes and instances while revisiting __init__, inheritance from object, instance dictionaries, and attribute lookup.
What you can do after
Build it from scratch by overriding protocol methods that make custom objects printable, callable, constructible, or lazily populated.
How it connects
Connects special methods to classes, inheritance, object-oriented programming, decorators, closures, data classes, and lazy attributes.

Also explained in

Compare how 3 books explain special method →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python How-To. The section links point to the parts of the book it draws on.