Skip to content

Callable Objects#

Python's callable protocol means anything with __call__ can be invoked like a function. Functions are one kind of callable — classes, bound methods, functools.partial, and custom objects can all implement __call__.

How to use this page

Connects functions, classes, and typing. See Higher Order Functions, Dunder or Magic Methods.

At a glance
Track Python Advanced → Advanced Functions
Sections 8 major topics
Outline Use the right-hand TOC to jump

Topics: What is callable? · Kinds of callables · Functor pattern — stateful callable object · Classes as callables · __call__ with decorators · Typing callables · operator module callables · Choosing: function vs functor vs partial

  1. What is callable?
  2. Kinds of callables
  3. Functor pattern — stateful callable object
  4. Classes as callables
  5. __call__ with decorators
  6. Typing callables
  7. operator module callables
  8. Choosing: function vs functor vs partial

What is callable?#

callable(print)        # True
callable(len)          # True
callable(42)           # False

def f(): pass
callable(f)            # True

Objects implementing __call__ return True for callable().


Kinds of callables#

Type Example Notes
Function def f(): ... __call__ on function type
Bound method obj.method self bound
Class MyClass() __call__ on metaclass for construction
Instance with __call__ obj() Functor pattern
partial partial(fn, 1) Pre-filled function
lambda lambda x: x Anonymous function
Built-in len, int C or Python builtin

Functor pattern — stateful callable object#

class Accumulator:
    def __init__(self):
        self.total = 0

    def __call__(self, x: int) -> int:
        self.total += x
        return self.total

acc = Accumulator()
acc(5)    # 5
acc(3)    # 8

Compare to closure counter in Closures — functor when you want named type, multiple methods, or inheritance.


Classes as callables#

Calling a class invokes __init__ after object creation:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

p = Point(1, 2)   # Point.__new__ then Point.__init__

Metaclasses customize class call — see Metaclasses.


__call__ with decorators#

Class-based decorators implement __call__ to wrap functions:

class CountCalls:
    def __init__(self, fn):
        self.fn = fn
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.count += 1
        return self.fn(*args, **kwargs)

@CountCalls
def work():
    print("working")

Typing callables#

from collections.abc import Callable

Handler = Callable[[str, int], bool]

def register(h: Handler) -> None:
    ...

# Callable with any args
Factory = Callable[..., object]

typing.Protocol for structural callables:

from typing import Protocol

class Runnable(Protocol):
    def __call__(self) -> None: ...

See Type Hints and Annotations.


operator module callables#

from operator import add, itemgetter, attrgetter

add(2, 3)                    # 5
itemgetter(1)([10, 20, 30])  # 20
attrgetter("name")(obj)

Pre-built callables avoid lambdas.


Choosing: function vs functor vs partial#

Need Choose
Simple one-off def
Fixed args to existing fn partial
Stateful + multiple methods Class with __call__
Lightweight state Closure
Pass to HOF / decorator Any callable

Interview traps (quick reference)#

Trap What goes wrong Safe approach
Confuse class call vs __call__ instance Wrong mental model Class() creates instance
Stateful functor shared Unintended shared state One instance per context
Wrong Callable type args Checker errors Match signature in Callable[[...], R]

Mental model checklist#

  1. What makes an object callable?
  2. How does a functor differ from a closure?
  3. What happens when you call a class?
  4. How do you type a function argument?

What's next#

Topic Page
Dunder methods Dunder or Magic Methods
Partial functions Partial Functions
Higher-order functions Higher Order Functions