The __call__ Method: Making Python Objects Behave Like Functions
- obj() calls obj.__class__.__call__(obj), so any object whose class defines __call__ can be used with function-call syntax.
- A callable class keeps state between calls in ordinary instance attributes, which is often clearer than a closure juggling nonlocal variables.
- Class-based decorators implement __call__ to wrap the decorated function, and often __init__ to accept decorator arguments.
- The built-in callable(obj) checks for __call__ without invoking it, useful for validating that a parameter is a function-like object.
Any object with __call__ can be called
Parentheses after an object — obj(args) — are syntax sugar for type(obj).__call__(obj, args). Functions are callable because the function type implements __call__; nothing stops any other class from implementing it too, at which point instances of that class can be invoked exactly like a function, while still carrying all the state and methods a normal object has:
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, value):
return value * self.factor
double = Multiplier(2)
triple = Multiplier(3)
print(double(21)) # 42 -- double is an instance, called like a function
print(triple(10)) # 30
print(callable(double)) # True
double here is a fully ordinary object — it has a factor attribute, it could have other methods, it could be pickled — it just also happens to be invokable with ().
Why a class beats a closure for stateful callables
A closure over nonlocal variables can achieve something similar, but a callable class scales better once the state has more than one or two fields, or needs to be inspected and modified from outside:
# Closure version: state hidden inside the closure, awkward to inspect or reset
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
# Class version: state is a normal, inspectable, resettable attribute
class Counter:
def __init__(self, start=0):
self.count = start
def __call__(self):
self.count += 1
return self.count
def reset(self):
self.count = 0
c = Counter()
print(c(), c(), c()) # 1 2 3
c.reset()
print(c.count) # 0 -- directly readable, unlike the closure's hidden count
The class version also supports adding more methods (reset above), subclassing, and straightforward unit testing by inspecting c.count directly, none of which a bare closure offers without extra plumbing.
Class-based decorators built on __call__
A common, practical use of __call__ is writing decorators as classes instead of nested functions, which becomes especially convenient once the decorator itself needs configuration arguments:
import functools
class retry:
def __init__(self, times=3):
self.times = times
def __call__(self, func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
last_exc = None
for attempt in range(self.times):
try:
return func(*args, **kwargs)
except Exception as exc:
last_exc = exc
raise last_exc
return wrapper
@retry(times=5)
def flaky_request():
...
# Equivalent to: flaky_request = retry(times=5)(flaky_request)
# retry(times=5) constructs an instance; calling that instance with flaky_request
# is what __call__ handles, returning the wrapped function.
Here @retry(times=5) first constructs a retry instance via __init__, then Python calls that instance with the decorated function as its argument — which is exactly the job __call__ does, returning the final wrapped function.
Checking callability with callable()
The built-in callable(obj) reports whether type(obj) defines __call__, without actually invoking anything. It's the right way to validate that a parameter someone passed in behaves like a function, regardless of whether it's an actual function, a lambda, a bound method, or a class instance implementing __call__:
def apply_twice(func, value):
if not callable(func):
raise TypeError(f"expected a callable, got {type(func).__name__}")
return func(func(value))
print(apply_twice(double, 5)) # 20 -- Multiplier(2) instance from earlier works fine
Where this shows up in real libraries
functools.partial objects are callable, implemented in C but conceptually identical to the Multiplier example. PyTorch and other machine-learning libraries make neural network layers callable so that layer(input_tensor) runs the forward pass while the layer object itself still holds its trained weights as ordinary attributes. Pytest fixtures and Click command objects lean on the same pattern. In all these cases the motivation is the same: something needs to look and behave like a plain function call at the point of use, while carrying configuration or state that a bare function has nowhere to put. The data model documentation for __call__ covers the exact signature Python expects.