Python __call__ Method
Last modified April 8, 2025
This comprehensive guide explores Python's __call__
method, which
makes instances callable like functions. We'll cover basic usage, stateful
functions, decorators, and practical examples.
Basic Definitions
The __call__
method enables instances to be called like functions.
When defined, you can use the instance with parentheses and arguments.
Key characteristics: it makes objects behave like functions, maintains state
between calls, and is essential for creating functors (function objects).
The method receives the instance as self
plus any call arguments.
Basic __call__ Implementation
Here's a simple class implementing __call__
to demonstrate the
basic functionality. The instance becomes callable like a function.
class Greeter: def __init__(self, greeting): self.greeting = greeting def __call__(self, name): return f"{self.greeting}, {name}!" hello = Greeter("Hello") print(hello("Alice")) # "Hello, Alice!" print(hello("Bob")) # "Hello, Bob!"
This example shows how __call__
makes instances behave like
functions. The Greeter
instance remembers its greeting
state between calls.
The hello
object can be called with parentheses and arguments,
just like a regular function, but maintains its own state.
Stateful Function Objects
__call__
is perfect for creating stateful function objects that
remember information between calls, unlike regular functions.
class Counter: def __init__(self): self.count = 0 def __call__(self): self.count += 1 return self.count counter = Counter() print(counter()) # 1 print(counter()) # 2 print(counter()) # 3
This Counter
class maintains state between calls. Each call
increments the count and returns the new value, demonstrating stateful behavior.
Unlike closure-based solutions, this approach provides a clean object-oriented way to maintain state between function calls with full class capabilities.
Creating Decorators with __call__
Class-based decorators often use __call__
to implement the
decorator logic while maintaining state between decorated function calls.
class Trace: def __init__(self, func): self.func = func self.calls = 0 def __call__(self, *args, **kwargs): self.calls += 1 print(f"Call {self.calls} to {self.func.__name__}") return self.func(*args, **kwargs) @Trace def square(x): return x * x print(square(5)) # Prints trace info and returns 25 print(square(3)) # Prints trace info and returns 9
This Trace
decorator logs each call to the decorated function.
The __call__
method handles the actual function invocation.
The decorator maintains state (call count) across multiple calls to the decorated function, demonstrating a key advantage of class-based decorators.
Memoization with __call__
The __call__
method can implement memoization by caching function
results to avoid repeated calculations for the same inputs.
class Memoize: def __init__(self, func): self.func = func self.cache = {} def __call__(self, *args): if args not in self.cache: self.cache[args] = self.func(*args) return self.cache[args] @Memoize def fibonacci(n): if n in (0, 1): return n return fibonacci(n-1) + fibonacci(n-2) print(fibonacci(10)) # 55 (cached results speed up calculation)
This memoization decorator caches Fibonacci sequence results to dramatically improve performance. The cache is maintained in the instance dictionary.
Each call first checks the cache before computing, storing new results for future use. This pattern works well for expensive pure functions.
Callable Objects for Configuration
__call__
can create flexible configuration objects that behave
differently based on call arguments while maintaining configuration state.
class Configurator: def __init__(self, default_mode="standard"): self.mode = default_mode self.settings = {} def __call__(self, mode=None, **options): if mode: self.mode = mode self.settings.update(options) return self def get_setting(self, key): return self.settings.get(key, f"default_{key}") config = Configurator() config(mode="debug", timeout=100, retries=3) print(config.mode) # "debug" print(config.get_setting("timeout")) # 100
This Configurator
class provides a fluent interface for
configuration. The __call__
method updates settings and returns
self for chaining.
The object maintains configuration state and can be called multiple times to adjust settings, offering a flexible alternative to configuration files.
Best Practices
- Maintain callable semantics: Make __call__ behave like a function
- Document call signature: Clearly document expected arguments
- Consider functools.wraps: For decorators, preserve function metadata
- Keep state clean: Manage instance state carefully between calls
- Prefer simple functions: Only use __call__ when state is needed
Source References
Author
List all Python tutorials.