Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using callable(x) vs. hasattr(x, "__call__")

I'm writing Python that targets versions 3.2 and higher. It looks like using the built-in function callable is the most straightforward and efficient way to do this. I've seen recommendations for hasattr(x, "__call__"), collections.Callable(x), and just using try/except around an attempted call.

I've tested items that are callable (a class and a function), using timeit with 100,000 iterations; in both cases using callable takes only about 75% of the time of checking for the attribute. When the item is not callable (an integer and a string) using callable stays at the same cost as a class or function while checking for the attribute is about 2.3 times more expensive than for a class or function. I didn't expect that difference, but it also favors the clear and concise callable(x) approach.

But I'm relatively new to Python and no expert, so are there reasons I'm not aware of that I should use the hasattr approach or another approach?

FWIW, the results of the various timeits follow. The first character is just t for timeit, the second indicates what the type of the object being tested (c = class, f = function, i = integer, s = string), and the rest indicates the method (attr - check attribute, call - use callable, try - use try/except).

tcattr 0.03665385400199739
tccall 0.026238360142997408
tctry 0.09736267629614304
tfattr 0.03624538065832894
tfcall 0.026362861895904643
tftry 0.032501874250556284
tiattr 0.08297350149314298
ticall 0.025826044152381655
titry 0.10657657453430147
tsattr 0.0840187013927789
tscall 0.02585409547373274
tstry 0.10742772077628615
like image 509
bmacnaughton Avatar asked May 05 '13 19:05

bmacnaughton


People also ask

What is callable () type in Python?

Definition and Usage The callable() function returns True if the specified object is callable, otherwise it returns False.

How do I call a callable in Python?

In Python, a callable is a function-like object, meaning it's something that behaves like a function. Just like with a function, you can use parentheses to call a callable.

What is a function call or a callable object in Python?

callable() in Python In general, a callable is something that can be called. This built-in method in Python checks and returns True if the object passed appears to be callable, but may not be, otherwise False.

What is a callable type?

Callable types These are the types to which the function call operation (see section Calls) can be applied: Is the operator for "the function call operatation" () ?


2 Answers

hasattr() will return more false positives than callable:

>>> class X(object):
...     def __getattr__(self, name):
...         return name
...
>>> i = X()
>>> from collections import Callable
>>> isinstance(i, Callable)
False
>>> callable(i)
False
>>> hasattr(i, '__call__')
True
>>> i()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'X' object is not callable

I'm not sure which callable you were testing, but both look nicer than hasattr and handle more cases, so I would use them in place of hasattr().

like image 160
Blender Avatar answered Oct 03 '22 20:10

Blender


callable is not only the fastest, but the Zen provides four more important reasons to use it instead of the other two contraptions:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Readability counts.

like image 25
phihag Avatar answered Oct 03 '22 20:10

phihag