Reputation: 10175
I have a variable, x
, and I want to know whether it is pointing to a function or not.
I had hoped I could do something like:
>>> isinstance(x, function)
But that gives me:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
The reason I picked that is because
>>> type(x)
<type 'function'>
Upvotes: 978
Views: 411826
Reputation: 941
def myfunc():
x = 1
print(isinstance(myfunc, type(lambda x:x)))
note that lambda x:x
is default funtion to get the type of function and compare it
Upvotes: 0
Reputation: 156268
The accepted answer is correct. As it
turns out, there is no substitute for callable()
, which is back in Python
3.2: Specifically, callable()
checks the tp_call
field of the object being
tested. There is no plain Python equivalent. Most of the suggested tests are
correct most of the time:
>>> class Spam(object):
... def __call__(self):
... return 'OK'
>>> can_o_spam = Spam()
>>> can_o_spam()
'OK'
>>> callable(can_o_spam)
True
>>> hasattr(can_o_spam, '__call__')
True
>>> import collections
>>> isinstance(can_o_spam, collections.Callable)
True
We can throw a monkey-wrench into this by removing the __call__
from the
class. And just to keep things extra exciting, add a fake __call__
to the instance!
>>> del Spam.__call__
>>> can_o_spam.__call__ = lambda *args: 'OK?'
Notice this really isn't callable:
>>> can_o_spam()
Traceback (most recent call last):
...
TypeError: 'Spam' object is not callable
callable()
returns the correct result:
>>> callable(can_o_spam)
False
But hasattr
is wrong:
>>> hasattr(can_o_spam, '__call__')
True
can_o_spam
does have that attribute after all; it's just not used when calling
the instance.
Even more subtle, isinstance()
also gets this wrong:
>>> isinstance(can_o_spam, collections.Callable)
True
Because we used this check earlier and later deleted the method, abc.ABCMeta
caches the result. Arguably this is a bug in abc.ABCMeta
. That said,
there's really no possible way it could produce a more accurate result than
the result than by using callable()
itself, since the typeobject->tp_call
slot method is not accessible in any other way.
Just use callable()
Upvotes: 91
Reputation: 11337
Try using callable(x)
.
Excerpt:
Return True if the object argument appears callable, False if not.
Upvotes: 18
Reputation: 1
With isinstance() and type() which are both built-in functions in Python below, you can check if it's a function so you don't need to import anything:
def test():
pass
print(isinstance(test, type(test)))
Output:
True
Upvotes: 0
Reputation: 107
it is my code:
# -*- coding: utf-8 -*-
import hashlib
import inspect
# calc everything to md5!!
def count_md5(content):
if isinstance(content, dict):
return count_md5(
[(str(k), count_md5(content[k])) for k in sorted(content.keys())],
)
elif isinstance(content, (list, tuple)):
content = [count_md5(k) for k in content]
elif callable(content):
return make_callable_hash(content)
return calc_md5(str(content))
def calc_md5(content):
m2 = hashlib.md5()
if isinstance(content, str):
m2.update(content.encode("utf8"))
else:
m2.update(content)
return m2.hexdigest()
def make_callable_hash(content):
if inspect.isclass(content):
h = []
for attr in [i for i in sorted(dir(content)) if not i.startswith("__")]:
v = getattr(content, attr)
h.append(count_md5(v))
return calc_md5("".join(h))
return calc_md5(content.__name__)
For callable, most of the time we just want to see if the values of the attributes are consistent, so we can take all the attributes of the callable
and evaluate it.
'callable' will return true if it's a class, so it's not very rigorous
Upvotes: 1
Reputation: 1117
callable(x) | hasattr(x, '__call__') | inspect.isfunction(x) | inspect.ismethod(x) | inspect.isgeneratorfunction(x) | inspect.iscoroutinefunction(x) | inspect.isasyncgenfunction(x) | isinstance(x, typing.Callable) | isinstance(x, types.BuiltinFunctionType) | isinstance(x, types.BuiltinMethodType) | isinstance(x, types.FunctionType) | isinstance(x, types.MethodType) | isinstance(x, types.LambdaType) | isinstance(x, functools.partial) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
√ | √ | × | × | × | × | × | √ | √ | √ | × | × | × | × | |
func | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
functools.partial | √ | √ | × | × | × | × | × | √ | × | × | × | × | × | √ |
<lambda> | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
generator | √ | √ | √ | × | √ | × | × | √ | × | × | √ | × | √ | × |
async_func | √ | √ | √ | × | × | √ | × | √ | × | × | √ | × | √ | × |
async_generator | √ | √ | √ | × | × | × | √ | √ | × | × | √ | × | √ | × |
A | √ | √ | × | × | × | × | × | √ | × | × | × | × | × | × |
meth | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
classmeth | √ | √ | × | √ | × | × | × | √ | × | × | × | √ | × | × |
staticmeth | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
import types
import inspect
import functools
import typing
def judge(x):
name = x.__name__ if hasattr(x, '__name__') else 'functools.partial'
print(name)
print('\ttype({})={}'.format(name, type(x)))
print('\tcallable({})={}'.format(name, callable(x)))
print('\thasattr({}, \'__call__\')={}'.format(name, hasattr(x, '__call__')))
print()
print('\tinspect.isfunction({})={}'.format(name, inspect.isfunction(x)))
print('\tinspect.ismethod({})={}'.format(name, inspect.ismethod(x)))
print('\tinspect.isgeneratorfunction({})={}'.format(name, inspect.isgeneratorfunction(x)))
print('\tinspect.iscoroutinefunction({})={}'.format(name, inspect.iscoroutinefunction(x)))
print('\tinspect.isasyncgenfunction({})={}'.format(name, inspect.isasyncgenfunction(x)))
print()
print('\tisinstance({}, typing.Callable)={}'.format(name, isinstance(x, typing.Callable)))
print('\tisinstance({}, types.BuiltinFunctionType)={}'.format(name, isinstance(x, types.BuiltinFunctionType)))
print('\tisinstance({}, types.BuiltinMethodType)={}'.format(name, isinstance(x, types.BuiltinMethodType)))
print('\tisinstance({}, types.FunctionType)={}'.format(name, isinstance(x, types.FunctionType)))
print('\tisinstance({}, types.MethodType)={}'.format(name, isinstance(x, types.MethodType)))
print('\tisinstance({}, types.LambdaType)={}'.format(name, isinstance(x, types.LambdaType)))
print('\tisinstance({}, functools.partial)={}'.format(name, isinstance(x, functools.partial)))
def func(a, b):
pass
partial = functools.partial(func, a=1)
_lambda = lambda _: _
def generator():
yield 1
yield 2
async def async_func():
pass
async def async_generator():
yield 1
class A:
def __call__(self, a, b):
pass
def meth(self, a, b):
pass
@classmethod
def classmeth(cls, a, b):
pass
@staticmethod
def staticmeth(a, b):
pass
for func in [print,
func,
partial,
_lambda,
generator,
async_func,
async_generator,
A,
A.meth,
A.classmeth,
A.staticmeth]:
judge(func)
Pick the three most common methods:
time/s | |
---|---|
callable(x) | 0.86 |
hasattr(x, '__call__') | 1.36 |
isinstance(x, typing.Callable) | 12.19 |
import typing
from timeit import timeit
def x():
pass
def f1():
return callable(x)
def f2():
return hasattr(x, '__call__')
def f3():
return isinstance(x, typing.Callable)
print(timeit(f1, number=10000000))
print(timeit(f2, number=10000000))
print(timeit(f3, number=10000000))
# 0.8643081
# 1.3563508
# 12.193492500000001
Upvotes: 40
Reputation: 1686
You can DIY a short function to check if the input is not string and cast the input to string will return matched name define:
def isFunction(o):return not isinstance(o,str) and str(o)[:3]=='<fu';
I think that this code is already compatible cross all python version.
Or if something change, you may add extra convert to lower case and check for content length. The format string casted of function I saw is "<function "+name+" at 0xFFFFFFFF>"
Upvotes: -4
Reputation: 311665
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.
Upvotes: 1235
Reputation: 193
combining @Sumukh Barve, @Katsu and @tinnick 's answers, and if your motive is just to grab the list of builtin functions available for your disposal in the console, these two options work:
[i for i, j in __builtin__.__dict__.items() if j.__class__.__name__ in ['function', 'builtin_function_or_method']]
[i for i, j in __builtin__.__dict__.items() if str(j)[:18] == '<built-in function']
Upvotes: 1
Reputation: 15336
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
.
Upvotes: 347
Reputation: 386
You could try this:
if obj.__class__.__name__ in ['function', 'builtin_function_or_method']:
print('probably a function')
or even something more bizarre:
if "function" in lower(obj.__class__.__name__):
print('probably a function')
Upvotes: 1
Reputation: 771
callable is a very good solution. However, I wanted to treat this the opposite way of John Feminella. Instead of treating it like this saying:
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. The "compare it directly" approach will give the wrong answer for many functions, like builtins.
We'll treat it like this:
The proper way to check if something is a duck is not to see if it can quack, but rather to see if it truly is a duck through several filters, instead of just checking if it seems like a duck from the surface.
The 'types' module has plenty of classes to detect functions, the most useful being types.FunctionType, but there are also plenty of others, like a method type, a built in type, and a lambda type. We also will consider a 'functools.partial' object as being a function.
The simple way we check if it is a function is by using an isinstance condition on all of these types. Previously, I wanted to make a base class which inherits from all of the above, but I am unable to do that, as Python does not allow us to inherit from some of the above classes.
Here's a table of what classes can classify what functions:
Above function table by kinght-金
Now, this is the code which does all of the work we described from above.
from types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, LambdaType
from functools import partial
def is_function(obj):
return isinstance(obj, (BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, LambdaType, partial))
#-------------------------------------------------
def my_func():
pass
def add_both(x, y):
return x + y
class a:
def b(self):
pass
check = [
is_function(lambda x: x + x),
is_function(my_func),
is_function(a.b),
is_function(partial),
is_function(partial(add_both, 2))
]
print(check)
>>> [True, True, True, False, True]
The one false was is_function(partial), because that's a class, not a function, and this is exactly functions, not classes. Here is a preview for you to try out the code from.
callable(obj) is the preferred method to check if an object is a function if you want to go by duck-typing over absolutes.
Our custom is_function(obj), maybe with some edits is the preferred method to check if an object is a function if you don't any count callable class instance as a function, but only functions defined built-in, or with lambda, def, or partial.
And I think that wraps it all up. Have a good day!
Upvotes: 7
Reputation: 22113
As the accepted answer, John Feminella stated that:
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. The "compare it directly" approach will give the wrong answer for many functions, like builtins.
Even though, there're two libs to distinguish functions strictly, I draw an exhaustive comparable table:
8.9. types — Dynamic type creation and names for built-in types — Python 3.7.0 documentation
30.13. inspect — Inspect live objects — Python 3.7.0 documentation
#import inspect #import types
['isabstract',
'isasyncgen', 'AsyncGeneratorType',
'isasyncgenfunction',
'isawaitable',
'isbuiltin', 'BuiltinFunctionType',
'BuiltinMethodType',
'isclass',
'iscode', 'CodeType',
'iscoroutine', 'CoroutineType',
'iscoroutinefunction',
'isdatadescriptor',
'isframe', 'FrameType',
'isfunction', 'FunctionType',
'LambdaType',
'MethodType',
'isgenerator', 'GeneratorType',
'isgeneratorfunction',
'ismethod',
'ismethoddescriptor',
'ismodule', 'ModuleType',
'isroutine',
'istraceback', 'TracebackType'
'MappingProxyType',
]
The "duck typing" is a preferred solution for general purpose:
def detect_function(obj):
return hasattr(obj,"__call__")
In [26]: detect_function(detect_function)
Out[26]: True
In [27]: callable(detect_function)
Out[27]: True
As for the builtins function
In [43]: callable(hasattr)
Out[43]: True
When go one more step to check if builtin function or user-defined funtion
#check inspect.isfunction and type.FunctionType
In [46]: inspect.isfunction(detect_function)
Out[46]: True
In [47]: inspect.isfunction(hasattr)
Out[47]: False
In [48]: isinstance(detect_function, types.FunctionType)
Out[48]: True
In [49]: isinstance(getattr, types.FunctionType)
Out[49]: False
#so they both just applied to judge the user-definded
Determine if builtin function
In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False
Summary
Employ callable
to duck type checking a function,
Use types.BuiltinFunctionType
if you have further specified demand.
Upvotes: 8
Reputation: 599
The following is a "repr way" to check it. Also it works with lambda.
def a():pass
type(a) #<class 'function'>
str(type(a))=="<class 'function'>" #True
b = lambda x:x*2
str(type(b))=="<class 'function'>" #True
Upvotes: -1
Reputation: 18341
If you have learned C++
, you must be familiar with function object
or functor
, means any object that can be called as if it is a function
.
In C++, an ordinary function
is a function object, and so is a function pointer; more generally, so is an object of a class that defines operator()
. In C++11 and greater, the lambda expression
is the functor
too.
Similarity, in Python, those functors
are all callable
. An ordinary function
can be callable, a lambda expression
can be callable, a functional.partial
can be callable, the instances of class with a __call__() method
can be callable.
Ok, go back to question : I have a variable, x, and I want to know whether it is pointing to a function or not.
If you want to judge weather the object acts like a function, then the
callable
method suggested by@John Feminella
is ok.If you want to
judge whether a object is just an ordinary function or not
( not a callable class instance, or a lambda expression), then thextypes.XXX
suggested by@Ryan
is a better choice.
#!/usr/bin/python3
# 2017.12.10 14:25:01 CST
# 2017.12.10 15:54:19 CST
import functools
import types
import pprint
Define a class and an ordinary function.
class A():
def __call__(self, a,b):
print(a,b)
def func1(self, a, b):
print("[classfunction]:", a, b)
@classmethod
def func2(cls, a,b):
print("[classmethod]:", a, b)
@staticmethod
def func3(a,b):
print("[staticmethod]:", a, b)
def func(a,b):
print("[function]", a,b)
Define the functors:
#(1.1) built-in function
builtins_func = open
#(1.2) ordinary function
ordinary_func = func
#(1.3) lambda expression
lambda_func = lambda a : func(a,4)
#(1.4) functools.partial
partial_func = functools.partial(func, b=4)
#(2.1) callable class instance
class_callable_instance = A()
#(2.2) ordinary class function
class_ordinary_func = A.func1
#(2.3) bound class method
class_bound_method = A.func2
#(2.4) static class method
class_static_func = A.func3
Define the functors' list and the types' list:
## list of functors
xfuncs = [builtins_func, ordinary_func, lambda_func, partial_func, class_callable_instance, class_ordinary_func, class_bound_method, class_static_func]
## list of type
xtypes = [types.BuiltinFunctionType, types.FunctionType, types.MethodType, types.LambdaType, functools.partial]
Judge wether the functor is callable. As you can see, they all are callable.
res = [callable(xfunc) for xfunc in xfuncs]
print("functors callable:")
print(res)
"""
functors callable:
[True, True, True, True, True, True, True, True]
"""
Judge the functor's type( types.XXX). Then the types of functors are not all the same.
res = [[isinstance(xfunc, xtype) for xtype in xtypes] for xfunc in xfuncs]
## output the result
print("functors' types")
for (row, xfunc) in zip(res, xfuncs):
print(row, xfunc)
"""
functors' types
[True, False, False, False, False] <built-in function open>
[False, True, False, True, False] <function func at 0x7f1b5203e048>
[False, True, False, True, False] <function <lambda> at 0x7f1b5081fd08>
[False, False, False, False, True] functools.partial(<function func at 0x7f1b5203e048>, b=4)
[False, False, False, False, False] <__main__.A object at 0x7f1b50870cc0>
[False, True, False, True, False] <function A.func1 at 0x7f1b5081fb70>
[False, False, True, False, False] <bound method A.func2 of <class '__main__.A'>>
[False, True, False, True, False] <function A.func3 at 0x7f1b5081fc80>
"""
Then you can choose the functors' types that suitable.
such as:
def func(a,b):
print("[function]", a,b)
>>> callable(func)
True
>>> isinstance(func, types.FunctionType)
True
>>> isinstance(func, (types.BuiltinFunctionType, types.FunctionType, functools.partial))
True
>>>
>>> isinstance(func, (types.MethodType, functools.partial))
False
Upvotes: 9
Reputation: 23243
Note that Python classes are also callable.
To get functions (and by functions we mean standard functions and lambdas) use:
import types
def is_func(obj):
return isinstance(obj, (types.FunctionType, types.LambdaType))
def f(x):
return x
assert is_func(f)
assert is_func(lambda x: x)
Upvotes: 4
Reputation: 6502
Since classes also have __call__
method, I recommend another solution:
class A(object):
def __init__(self):
pass
def __call__(self):
print 'I am a Class'
MyClass = A()
def foo():
pass
print hasattr(foo.__class__, 'func_name') # Returns True
print hasattr(A.__class__, 'func_name') # Returns False as expected
print hasattr(foo, '__call__') # Returns True
print hasattr(A, '__call__') # (!) Returns True while it is not a function
Upvotes: 4
Reputation: 1444
Here's a couple of other ways:
def isFunction1(f) :
return type(f) == type(lambda x: x);
def isFunction2(f) :
return 'function' in str(type(f));
Here's how I came up with the second:
>>> type(lambda x: x);
<type 'function'>
>>> str(type(lambda x: x));
"<type 'function'>"
# Look Maa, function! ... I ACTUALLY told my mom about this!
Upvotes: 6
Reputation: 7344
The solutions using hasattr(obj, '__call__')
and callable(.)
mentioned in some of the answers have a main drawback: both also return True
for classes and instances of classes with a __call__()
method. Eg.
>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True
One proper way of checking if an object is a user-defined function (and nothing but a that) is to use isfunction(.)
:
>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True
If you need to check for other types, have a look at inspect — Inspect live objects.
Upvotes: 2
Reputation: 15734
If the code will go on to perform the call if the value is callable, just perform the call and catch TypeError
.
def myfunc(x):
try:
x()
except TypeError:
raise Exception("Not callable")
Upvotes: -1
Reputation: 7009
Instead of checking for '__call__'
(which is not exclusive to functions), you can check whether a user-defined function has attributes func_name
, func_doc
, etc. This does not work for methods.
>>> def x(): pass
...
>>> hasattr(x, 'func_name')
True
Another way of checking is using the isfunction()
method from the inspect
module.
>>> import inspect
>>> inspect.isfunction(x)
True
To check if an object is a method, use inspect.ismethod()
Upvotes: 4
Reputation: 1958
Whatever function is a class so you can take the name of the class of instance x and compare:
if(x.__class__.__name__ == 'function'):
print "it's a function"
Upvotes: 3
Reputation: 20664
Following previous replies, I came up with this:
from pprint import pprint
def print_callables_of(obj):
li = []
for name in dir(obj):
attr = getattr(obj, name)
if hasattr(attr, '__call__'):
li.append(name)
pprint(li)
Upvotes: 0
Reputation: 25695
Python's 2to3 tool (http://docs.python.org/dev/library/2to3.html) suggests:
import collections
isinstance(obj, collections.Callable)
It seems this was chosen instead of the hasattr(x, '__call__')
method because of http://bugs.python.org/issue7006.
Upvotes: 26
Reputation: 2710
If you want to detect everything that syntactically looks like a function: a function, method, built-in fun/meth, lambda ... but exclude callable objects (objects with __call__
method defined), then try this one:
import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))
I compared this with the code of is*()
checks in inspect
module and the expression above is much more complete, especially if your goal is filtering out any functions or detecting regular properties of an object.
Upvotes: 17
Reputation: 21146
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
Upvotes: 109
Reputation: 11
In Python3 I came up with type (f) == type (lambda x:x)
which yields True
if f
is a function and False
if it is not. But I think I prefer isinstance (f, types.FunctionType)
, which feels less ad hoc. I wanted to do type (f) is function
, but that doesn't work.
Upvotes: 1
Reputation: 169673
A function is just a class with a __call__
method, so you can do
hasattr(obj, '__call__')
For example:
>>> hasattr(x, '__call__')
True
>>> x = 2
>>> hasattr(x, '__call__')
False
That is the "best" way of doing it, but depending on why you need to know if it's callable or note, you could just put it in a try/execpt block:
try:
x()
except TypeError:
print "was not callable"
It's arguable if try/except is more Python'y than doing if hasattr(x, '__call__'): x()
.. I would say hasattr
is more accurate, since you wont accidently catch the wrong TypeError, for example:
>>> def x():
... raise TypeError
...
>>> hasattr(x, '__call__')
True # Correct
>>> try:
... x()
... except TypeError:
... print "x was not callable"
...
x was not callable # Wrong!
Upvotes: 5
Reputation: 90289
callable(x)
will return true if the object passed can be called in Python, but the function does not exist in Python 3.0, and properly speaking will not distinguish between:
class A(object):
def __call__(self):
return 'Foo'
def B():
return 'Bar'
a = A()
b = B
print type(a), callable(a)
print type(b), callable(b)
You'll get <class 'A'> True
and <type function> True
as output.
isinstance
works perfectly well to determine if something is a function (try isinstance(b, types.FunctionType)
); if you're really interested in knowing if something can be called, you can either use hasattr(b, '__call__')
or just try it.
test_as_func = True
try:
b()
except TypeError:
test_as_func = False
except:
pass
This, of course, won't tell you whether it's callable but throws a TypeError
when it executes, or isn't callable in the first place. That may not matter to you.
Upvotes: 19