Back to Blog
Python

Python Callable Objects: How to Make Instances Callable

Learn how to make Python instances callable with `__call__`, and see how stateful callable objects work well for callbacks, decorators, and configurable factories.

callable__call__object-orientedfunctionsdecoratorspython
Illustration of a Python object with a call button, representing callable objects and the __call__ method.

What Makes an Object Callable?

In Python, a callable object is any object you can invoke with parentheses. Functions, classes, methods, and many built-in objects are callable. An instance becomes callable when its class implements the __call__ method. The language checks for the presence of __call__ on the object's class, and you can verify this with the built-in callable() function:

class Greeter: def __call__(self, name): print(f"Hello, {name}") g = Greeter() print(callable(g)) # True g("Alice") # Hello, Alice

The __call__ method is what turns a regular instance into something that behaves like a function. This is part of Python's data model and is used throughout the standard library and third-party libraries.

Implementing call

To make a custom object callable, define a __call__ method on its class. The method can accept any arguments, just like a regular function, and can return a value. Here is a simple counter that increments each time it is called:

class Counter: def __init__(self, start=0): self.count = start def __call__(self): self.count += 1 return self.count counter = Counter(10) print(counter()) # 11 print(counter()) # 12

The instance retains state between calls, which is often useful compared with a plain function. The __call__ method can also accept positional and keyword arguments, and you can combine it with other methods on the class.

Callable Objects vs Functions

A plain function is the simplest callable, but a callable object can carry state and additional methods. Use a callable object when you need to keep configuration or state across calls, or when you want to bundle related behavior with data. If stateful behavior must be available to other methods, a callable object keeps that state and related methods in one place.

class ExponentialAverage: def __init__(self, alpha): self.alpha = alpha self.avg = None def __call__(self, value): if self.avg is None: self.avg = value else: self.avg = self.alpha * value + (1 - self.alpha) * self.avg return self.avg

Here the state is stored in the instance, making the object reusable and testable. A closure could achieve the same, but a callable object is often clearer when the logic becomes complex or when you need to expose additional methods.

Practical Use Cases

Callable objects appear in several common Python patterns:

  • Decorators: A class-based decorator can implement __call__ to wrap functions while preserving state.
  • Factories: A callable factory can be configured with parameters and then invoked to create new objects.
  • Callbacks: GUI or event-driven code often uses callable objects as callbacks that carry context.
  • Partial application: You can create a callable object that stores some arguments and applies them later.

For instance, a simple decorator that logs function calls:

class LoggingDecorator: def __init__(self, func): self.func = func self.calls = 0 def __call__(self, *args, **kwargs): self.calls += 1 print(f"Call {self.calls} of {self.func.__name__}") return self.func(*args, **kwargs) @LoggingDecorator def add(a, b): return a + b print(add(2, 3)) # logs and returns 5

The decorator instance holds the original function and a call counter. This pattern is more explicit than a closure when the decorator needs to expose attributes or methods.

Common Mistakes and Pitfalls

One common mistake is forgetting to define __call__ and then trying to call an instance. This raises a TypeError: 'MyClass' object is not callable. Always verify with callable() if you are unsure.

Another pitfall is relying on mutable state without understanding the lifecycle. A callable object that is shared across threads can cause race conditions. If you need thread safety, add appropriate locks or use thread-local state.

Also, be careful when using callable objects as default arguments in functions. The object is created once at definition time, so any state it carries persists across calls. This can lead to surprising behavior if you intended a fresh state each time.

Performance and Memory Considerations

Calling an instance that implements __call__ can carry a small overhead compared with calling a plain function directly. In most applications this is negligible. If you are writing performance-critical code, measure with timeit before optimizing.

A callable object is an instance, so it usually has its own attribute dictionary and uses more memory than a stateless function. If you only need a simple callable with no state, a plain function or lambda is usually simpler and more memory-efficient.

Advanced: Callable Objects with Parameters

You can combine __call__ with __init__ to create configurable callables. For example, a multiplier that is configured with a factor:

class Multiplier: def __init__(self, factor): self.factor = factor def __call__(self, value): return value * self.factor double = Multiplier(2) print(double(5)) # 10

This is similar to using functools.partial but gives you a full class. You can also implement __repr__ to make the object easier to debug. The flexibility of a callable object makes it a powerful tool for building clean, stateful abstractions.

Python Callable Objects: Practical Usage and Code Examples | RYUSLOG DEV