ravron
ravron

Reputation: 11221

When can calls to a callable() still fail?

The documentation for callable() in Python 3.6 (and for Python 2.7) says in part:

If this returns true, it is still possible that a call fails, but if it is false, calling object will never succeed.

What does it mean to "fail" in this case? Just "standard" function call failures like mismatched arguments, or a raised exception? If something else is meant, what?

In short, in what cases can callable(obj) return true but calling obj() fail?

Upvotes: 4

Views: 234

Answers (1)

abarnert
abarnert

Reputation: 365915

First, it's trivially true that any function call can fail. Maybe you mutated the object between checking callable and calling it. Or maybe the object is callable, but you passed it invalid arguments, or it raised an exception during operation, or the user just hit ^C, …

But that's not what the docs are warnings about. They're telling you that you can get a TypeError: <something> is not callable from doing func() even if callable(func) returned True.

While this isn't exactly documented (maybe to allow other implementations to optimize things?), callable is essentially implemented as:

def callable(object):
    return hasattr(object, '__call__')

And this is at least implied, if not directly stated:

Note that classes are callable (calling a class returns a new instance); instances are callable if their class has a __call__() method.

The key is that really everything is an instance. (Classes are instances of their metaclass, which always has a __call__ method.)


So, it's very easy to create something that breaks the test. One way is to just give it a non-callable __call__:

>>> class C:
...     __call__ = 0
>>> c = C()
>>> callable(c)
True
>>> c()
TypeError: 'int' object is not callable

Also, notice that claiming that false negatives are impossible ("if it is false, calling object will never succeed") implies that special method lookup on the __call__ method must use the same mechanism as callable (or a strictly weaker one). So, for example, if a Python implementation chooses not to ignore metaclass __getattribute__ lookup or instance __dict__ lookup for __call__, its callable must do the same. And you can see this (at least in CPython 3.7):

>>> class D:
...     pass
>>> d = D()
>>> d.__call__ = 0
>>> callable(d)
False
>>> d()
TypeError: 'D' object is not callable

(Testing the other special method lookup possibilities is left as an exercise for the reader, meaning I'm too lazy to write them all and happy enough guessing they'll all go the same way…)


In CPython, callable actually just calls the C API method PyCallable_Check. And that function just checks that the object's type has a tp_call slot. For types implemented in Python, that will be true iff __call__ was defined directly on the class or a base class.

Upvotes: 4

Related Questions