Skip to content

How to Create Callable Objects in Python Using __call__ Method

1. The Problem

I was reading through some Python library code when I encountered this confusing syntax:

multiplier = Multiplier(3)
result = multiplier(5) # Wait, I'm calling an object instance like a function?
print(result) # Output: 15

At first, I thought maybe multiplier was somehow a function, not an instance. But no, Multiplier(3) clearly creates an object instance. So how can I call an instance like a function with multiplier(5)?

Then I saw an even more confusing pattern:

result = SomeClass()() # Double parentheses on a class?

I was completely lost. In my mental model, you call functions with (), not object instances. What was going on here?

2. What I Initially Thought (Wrong!)

My first instinct was to assume this was some kind of Python magic I didn’t understand. I had a few wrong theories:

Theory 1: Maybe multiplier is actually a function reference?

wrong_theory_1.py
# I thought maybe it was like this:
multiplier = some_function # Reference to a function
result = multiplier(5) # This makes sense

But that didn’t explain the Multiplier(3) part clearly creating an instance.

Theory 2: Maybe there’s some inheritance from a callable base class?

wrong_theory_2.py
# I thought maybe:
class Multiplier(SomeCallableBaseClass): # Does this exist?
...

I was overcomplicating things. The real answer is much simpler.

3. Discovering the __call__ Method

After some research, I discovered that Python has a special method called __call__ that makes object instances callable. This was my “aha” moment.

Let me show you the simplest example:

basic_call.py
class Greeter:
def __init__(self, name):
self.name = name
def __call__(self, greeting):
"""This method is called when you use () on an instance"""
return f"{greeting}, {self.name}!"
# Create an instance
greeter = Greeter("Alice")
# Now call the instance like a function!
result = greeter("Hello")
print(result) # Output: Hello, Alice!

When I ran this code:

Hello, Alice!

So the __call__ method is what makes instances callable. When you write greeter("Hello"), Python is actually calling greeter.__call__("Hello").

4. Understanding What “Callable” Means

Before diving deeper, let me clarify what “callable” means in Python. A callable is anything you can invoke with the () syntax.

check_callable.py
# Check what's callable using the built-in callable() function
# Functions are callable
print(callable(len)) # True
print(callable(print)) # True
# Classes are callable (they create instances)
print(callable(list)) # True
print(callable(dict)) # True
# Most objects are NOT callable by default
print(callable("hello")) # False
print(callable(42)) # False
print(callable([1, 2, 3])) # False
# But with __call__, instances become callable
class MyCallable:
def __call__(self):
return "I'm callable!"
obj = MyCallable()
print(callable(obj)) # True

Output:

True
True
True
True
False
False
False
True

This helped me understand: Python doesn’t care what something is, only what it can do. This is duck typing in action - if it has __call__, it’s callable.

5. Practical Examples

Once I understood the basics, I started seeing practical uses everywhere. Here are the patterns I found most useful:

5.1 Stateful Functions

This is perhaps the most common use case - functions that remember state between calls:

stateful_counter.py
class Counter:
"""A counter that maintains state across calls"""
def __init__(self, start=0):
self.count = start
def __call__(self, increment=1):
self.count += increment
return self.count
# Create independent counters
my_counter = Counter(10)
your_counter = Counter(100)
print(my_counter()) # 11
print(my_counter()) # 12
print(my_counter(5)) # 17
print(your_counter()) # 101
print(my_counter()) # 18 - still remembers its own state

Output:

11
12
17
101
18

Each counter maintains its own state. This is cleaner than using global variables or closures.

5.2 Configuration Objects

I found this pattern useful for creating configurable validators:

configurable_validator.py
class Validator:
"""A configurable validator that can be called like a function"""
def __init__(self, min_length, max_length, allowed_chars=None):
self.min_length = min_length
self.max_length = max_length
self.allowed_chars = allowed_chars
def __call__(self, value):
if not isinstance(value, str):
raise TypeError("Value must be a string")
if not self.min_length <= len(value) <= self.max_length:
return False
if self.allowed_chars and not all(c in self.allowed_chars for c in value):
return False
return True
# Create specialized validators
username_validator = Validator(3, 20, allowed_chars="abcdefghijklmnopqrstuvwxyz0123456789_")
password_validator = Validator(8, 100)
comment_validator = Validator(1, 500)
# Use them like functions
print(username_validator("alice123")) # True
print(username_validator("ab")) # False - too short
print(username_validator("alice@123")) # False - @ not allowed
print(password_validator("secret123")) # True

Output:

True
False
False
True

5.3 Decorator Classes

Many decorators are implemented as callable classes because they need to maintain state:

decorator_class.py
import time
class Timer:
"""A decorator that times function calls"""
def __init__(self, precision=2):
self.precision = precision
self.total_time = 0
self.call_count = 0
def __call__(self, func):
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
self.total_time += elapsed
self.call_count += 1
print(f"{func.__name__} took {elapsed:.{self.precision}f}s")
return result
return wrapper
# Usage
timer = Timer(precision=4)
@timer
def slow_function():
time.sleep(0.1)
return "done"
slow_function()
slow_function()
slow_function()
print(f"Total calls: {timer.call_count}, Total time: {timer.total_time:.4f}s")

Sample output:

slow_function took 0.1003s
slow_function took 0.1002s
slow_function took 0.1001s
Total calls: 3, Total time: 0.3006s

5.4 API Design Pattern

Callable objects can provide intuitive APIs for configuration:

api_pattern.py
class Database:
def __init__(self, host, port):
self.host = host
self.port = port
self._connected = False
def __call__(self, query):
"""Make the instance itself execute queries"""
if not self._connected:
raise RuntimeError("Not connected to database")
return f"Executing: {query} on {self.host}:{self.port}"
def connect(self):
self._connected = True
print(f"Connected to {self.host}:{self.port}")
def disconnect(self):
self._connected = False
print("Disconnected")
# Intuitive API
db = Database("localhost", 5432)
db.connect()
# Now call the instance to execute queries
result = db("SELECT * FROM users")
print(result)
db.disconnect()

Output:

Connected to localhost:5432
Executing: SELECT * FROM users on localhost:5432
Disconnected

6. The Difference Between __init__ and __call__

This was a point of confusion for me initially, so let me clarify:

init_vs_call.py
class Example:
def __init__(self, name):
"""Called when creating an instance"""
print(f"__init__ called with name={name}")
self.name = name
def __call__(self, value):
"""Called when you use () on an instance"""
print(f"__call__ called with value={value}")
return f"{self.name}: {value}"
# __init__ is called here
obj = Example("MyObject")
# Output: __init__ called with name=MyObject
# __call__ is called here
result = obj("hello")
# Output: __call__ called with value=hello
print(result)
# Output: MyObject: hello

Output:

__init__ called with name=MyObject
__call__ called with value=hello
MyObject: hello

The key distinction:

  • __init__ is called when you create an instance: ClassName(args) calls __init__
  • __call__ is called when you call an instance: instance(args) calls __call__

7. Understanding Chained Calls: foo()()

Now I finally understand what foo()() means:

chained_calls.py
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, value):
return value * self.factor
def get_multiplier(factor):
"""Returns a callable Multiplier instance"""
return Multiplier(factor)
# Chained call breakdown:
# 1. get_multiplier(3) returns a Multiplier instance
# 2. That instance is callable (has __call__)
# 3. (10) calls that instance
result = get_multiplier(3)(10)
print(result) # 30
# Equivalent to:
multiplier_obj = get_multiplier(3) # Returns Multiplier(3)
result = multiplier_obj(10) # Calls __call__ on that instance
print(result) # 30

Output:

30
30

So foo()() works because:

  1. foo() returns something (could be a function, or a class instance with __call__)
  2. That something is callable
  3. () calls it

8. Common Mistakes

I made several mistakes while learning this:

Mistake 1: Trying to Call Non-Callable Objects

mistake_not_callable.py
class NotCallable:
def __init__(self, value):
self.value = value
# No __call__ method!
obj = NotCallable(42)
obj() # TypeError: 'NotCallable' object is not callable

Error:

TypeError: 'NotCallable' object is not callable

The fix: Always check with callable() if you’re unsure.

Mistake 2: Confusing __call__ with Instance Methods

mistake_method.py
class BadExample:
def __call__(self, value):
return value * 2
def process(self, value):
return value * 2
obj = BadExample()
# These look similar but work differently:
print(obj(5)) # Calls __call__: 10
print(obj.process(5)) # Calls the method: 10
# The difference becomes clear with assignment:
my_func = obj # Reference to the callable instance
print(my_func(5)) # Still works: 10
my_method = obj.process # Reference to the bound method
print(my_method(5)) # Works: 10
# But they're different types:
print(type(obj)) # <class '__main__.BadExample'>
print(type(obj.process)) # <class 'method'>

Mistake 3: Not Handling State Correctly

mistake_state.py
class BuggyCounter:
count = 0 # Class variable - shared by all instances!
def __call__(self):
self.count += 1
return self.count
counter1 = BuggyCounter()
counter2 = BuggyCounter()
print(counter1()) # 1
print(counter1()) # 2
print(counter2()) # 3 - Wait, why not 1?

The problem: using a class variable instead of instance variable.

fixed_state.py
class FixedCounter:
def __init__(self):
self.count = 0 # Instance variable - separate for each instance
def __call__(self):
self.count += 1
return self.count
counter1 = FixedCounter()
counter2 = FixedCounter()
print(counter1()) # 1
print(counter1()) # 2
print(counter2()) # 1 - Correct!

Output:

1
2
1

9. Summary

I learned that Python’s callable objects, powered by the __call__ method, provide a powerful way to create function-like classes. The key insights are:

  1. Any object with __call__ is callable: Python uses duck typing - if it has __call__, you can use () on it.

  2. __init__ vs __call__:

    • __init__ is called when creating an instance: ClassName()
    • __call__ is called when calling an instance: instance()
  3. Practical uses:

    • Stateful functions that remember values between calls
    • Configurable validators and processors
    • Decorator classes with state
    • Intuitive API design
  4. Chained calls work because foo()() is just calling whatever foo() returns - if that return value is callable, the second () works.

Now when I see code like obj() or foo()(), I immediately know what’s happening: somewhere in the inheritance chain, there’s a __call__ method making that object callable.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments