The Python Oracle

How do I detect whether a Python variable is a function?

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: RPG Blues Looping

--

Chapters
00:00 Question
00:38 Accepted answer (Score 1172)
02:01 Answer 2 (Score 332)
03:21 Answer 3 (Score 105)
03:38 Answer 4 (Score 86)
05:33 Thank you

--

Full question
https://stackoverflow.com/questions/6249...

Accepted answer links:
[callable()]: https://docs.python.org/3/library/functi...
http://bugs.python.org/issue10518
[types.FunctionTypes]: https://docs.python.org/3/library/types....
[inspect.isfunction]: https://docs.python.org/3/library/inspec...
[the exact same thing]: https://github.com/python/cpython/blob/e...
[builtin functions]: https://docs.python.org/3/library/functi...

Answer 3 links:
[Since Python 2.1]: http://docs.python.org/library/inspect.h...
[inspect]: http://docs.python.org/library/inspect.h...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ACCEPTED ANSWER

Score 1224


If this is for Python 2.x or for Python 3.2+, you can use callable(). It used to be deprecated, but is now undeprecated, so you can use it again. You can read the discussion here: http://bugs.python.org/issue10518. You can do this with:

callable(obj)

If this is for Python 3.x but before 3.2, check if the object has a __call__ attribute. You can do this with:

hasattr(obj, '__call__')

The oft-suggested types.FunctionTypes or inspect.isfunction approach (both do the exact same thing) comes with a number of caveats. It returns False for non-Python functions. Most builtin functions, for example, are implemented in C and not Python, so they return False:

>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True

so types.FunctionType might give you surprising results. The proper way to check properties of duck-typed objects is to ask them if they quack, not to see if they fit in a duck-sized container.




ANSWER 2

Score 346


Builtin types that don't have constructors in the built-in namespace (e.g. functions, generators, methods) are in the types module. You can use types.FunctionType in an isinstance call:

>>> import types
>>> types.FunctionType
<class 'function'>

>>> def f(): pass

>>> isinstance(f, types.FunctionType)
True
>>> isinstance(lambda x : None, types.FunctionType)
True

Note that this uses a very specific notion of "function" that is usually not what you need. For example, it rejects zip (technically a class):

>>> type(zip), isinstance(zip, types.FunctionType)
(<class 'type'>, False)

open (built-in functions have a different type):

>>> type(open), isinstance(open, types.FunctionType)
(<class 'builtin_function_or_method'>, False)

and random.shuffle (technically a method of a hidden random.Random instance):

>>> type(random.shuffle), isinstance(random.shuffle, types.FunctionType)
(<class 'method'>, False)

If you're doing something specific to types.FunctionType instances, like decompiling their bytecode or inspecting closure variables, use types.FunctionType, but if you just need an object to be callable like a function, use callable.




ANSWER 3

Score 109


Since Python 2.1 you can import isfunction from the inspect module.

>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True



ANSWER 4

Score 54


The following should return a boolean:

callable(x)