The Built-In callable() Function

by Christoph Schiessl on Python

Another useful and interesting built-in function is callable(object), which the official documentation explains as follows:

Return True if the object argument appears callable, False if not. If this returns True, it is still possible that a call fails, but if it is False, calling object will never succeed. Note that classes are callable (calling a class returns a new instance); instances are callable if their class has a __call__() method.

This sounds easy enough, so let's try it out:

>>> def custom_function():
...     pass
...
>>> callable(custom_function)
True
>>> custom_lambda = lambda: None
>>> callable(custom_lambda)
True

Ordinary functions and lambdas are obviously callable. Everything else wouldn't make much sense, would it?

>>> callable(list)
True
>>> class CustomClass:
...     pass
...
>>> callable(CustomClass)
True

Both, built-in classes (e.g., list) and user-defined classes (e.g., CustomClass), are also callable. As a matter of fact, classes are always callable, and if you do call them, you get a new instance of the class as the return value.

>>> callable(list())
False
>>> callable([])
False
>>> class CustomClass:
...     pass
...
>>> callable(CustomClass)
True

Objects — aka instances of classes — are a different story. For example, instances of list are not callable. By the way, list() and [] are the same thing; both create a new instance of the list class, and in both cases, the newly created list object doesn't contain elements. In other words, the two new lists are empty.

>>> class CustomClass:
...     pass
...
>>> callable(CustomClass)
True
>>> callable(CustomClass())
False
>>> class CustomCallableClass:
...     def __call__(self):
...         pass
...
>>> callable(CustomCallableClass)
True
>>> callable(CustomCallableClass())
True

User-defined classes are not callable by default unless they define the dunder method __call__(), which is what the CustomCallableClass in the example above is doing.

You can also understand callable objects as follows: An object x = SomeClass() can be called as x() if and only if it is callable(x) == True. If you call an object like this, what's happening behind the scenes is roughly equivalent to type(x).__call__(x). This works because type(x) == SomeClass.

>>> class SomeClass:
...     def __call__(self): # Add parameters if you need to ...
...         print(f"{type(self).__name__}.__call__() has been called!")
...
>>> x = SomeClass()
>>> x()
SomeClass.__call__() has been called!
>>> type(x).__call__(x)
SomeClass.__call__() has been called!

Isn't this all fascinating? The point of this article was to demonstrate that everything in Python is potentially callable. Thank you for reading, and as always, please don't hesitate to reach out if you have any comments or questions.

Web App Reverse Checklist

Ready to Build Your Next Web App?

Get my Web App Reverse Checklist first ...


Software Engineering is often driven by fashion, but swimming with the current is rarely the best choice. In addition to knowing what to do, it's equally important to know what not to do. And this is precisely what my free Web App Reverse Checklist will help you with.

Subscribe below to get your free copy of my Reverse Checklist delivered to your inbox. Afterward, you can expect one weekly email on building resilient Web Applications using Python, JavaScript, and PostgreSQL.

By the way, it goes without saying that I'm not sharing your email address with anyone, and you're free to unsubscribe at any time. No spam. No commitments. No questions asked.

Continue Reading?

Here are a few more Articles for you ...


The Built-In any() Function

Learn how to use the built-in any() function in Python to determine if any element in an iterable is True, with implementation and performance insights.

By Christoph Schiessl on Python

Exploring Orphaned Branches to Understand Git's Internals

Learn about Git's internal data structure and how orphaned branches can be used to create separate histories with their own root commits.

By Christoph Schiessl on DevOps and Git

How to <link> your Blog's Atom/RSS Feed from HTML Pages

Learn how to <link> Atom and RSS feeds from your HTML documents to make them discoverable for clients and, by extension, for your readers.

By Christoph Schiessl

Christoph Schiessl

Hi, I'm Christoph Schiessl.

I help you build robust and fast Web Applications.


I'm available for hire as a freelance web developer, so you can take advantage of my more than a decade of experience working on many projects across several industries. Most of my clients are building web-based SaaS applications in a B2B context and depend on my expertise in various capacities.

More often than not, my involvement includes hands-on development work using technologies like Python, JavaScript, and PostgreSQL. Furthermore, if you already have an established team, I can support you as a technical product manager with a passion for simplifying complex processes. Lastly, I'm an avid writer and educator who takes pride in breaking technical concepts down into the simplest possible terms.