13

I've got a list of things, of which some can also be functions. If it is a function I would like to execute it. For this I do a type-check. This normally works for other types, like str, int or float. But for a function it doesn't seem to work:

>>> def f():
...     pass
... 
>>> type(f)
<type 'function'>
>>> if type(f) == function: print 'It is a function!!'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'function' is not defined
>>>

Does anybody know how I can check for a function type?

kramer65
  • 50,427
  • 120
  • 308
  • 488

4 Answers4

19

Don't check types, check actions. You don't actually care if it's a function (it might be a class instance with a __call__ method, for example) - you just care if it can be called. So use callable(f).

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
4

Because function isn't a built-in type, a NameError is raised. If you want to check whether something is a function, use hasattr:

>>> hasattr(f, '__call__')
True

Or you can use isinstance():

>>> from collections import Callable
>>> isinstance(f, Callable)
True
>>> isinstance(map, Callable)
True
TerryA
  • 58,805
  • 11
  • 114
  • 143
  • `isinstance` is not good for `isinstance(map, types.FunctionType)` returns `False`. Builtin functions are different not to mention the callable class. – zhangyangyu Jul 12 '13 at 10:33
  • @zhangyangyu For built-in functions, you can use `inspect.isbuiltin` – TerryA Jul 12 '13 at 10:34
  • 1
    There is `collections.Callable`. It works for buitlin functions too: `isinstance(map, collections.Callable)` returns `True` – stalk Jul 12 '13 at 10:35
  • @stalk - What's the difference between collections.Callable and simply callable (as suggested by DanielRoseman)? – kramer65 Jul 12 '13 at 10:39
  • @kramer65 well, i think it just another solution. `callable()` looks like more simplier. – stalk Jul 12 '13 at 10:44
  • @kramer65 I did some research, it looks like callable was considered deprecated, and was actually removed in python 3.0 as it was suggested to use collections.Callable. However, it was put back in in 3.1 – TerryA Jul 12 '13 at 10:45
  • @kramer65 `callable` is a built-in function. `collections.Callable` is [an abstract base class for classes that provide the __call__() method](http://docs.python.org/2/library/collections.html#collections.Callable). I don't see any reason to use the latter for this purpose. – Paulo Almeida Jul 12 '13 at 10:47
4
import types

if type(f) == types.FunctionType: 
    print 'It is a function!!'
Maerlyn
  • 33,687
  • 18
  • 94
  • 85
3

collections.Callable can be used:

import collections

print isinstance(f, collections.Callable)
stalk
  • 11,934
  • 4
  • 36
  • 58
  • And in new-ish Python 3 versions (I think it's 3.2+) `callable` is re-introduced as a shorthand for this. –  Jul 12 '13 at 10:45