If this is for Python 2.x or for Python 3.2+, you can also 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 approach is not correct because it fails to cover many cases that you would presumably want it to pass, like with builtins:
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. Don’t use types.FunctionType unless you have a very specific idea of what a function is.
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:
In [1]: import types
In [2]: types.FunctionType
Out[2]: <type 'function'>
In [3]: def f(): pass
...:
In [4]: isinstance(f, types.FunctionType)
Out[4]: True
In [5]: isinstance(lambda x : None, types.FunctionType)
Out[5]: 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):
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.
The accepted answer was at the time it was offered thought to be 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:
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:
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.
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.
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.
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:
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.
class A():def __call__(self, a,b):print(a,b)def func1(self, a, b):print("[classfunction]:", a, b)@classmethoddef func2(cls, a,b):print("[classmethod]:", a, b)@staticmethoddef func3(a,b):print("[staticmethod]:", a, b)def func(a,b):print("[function]", a,b)
定义函子:
#(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
定义函子列表和类型列表:
## 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]
判断函子是否可调用。如您所见,它们都是可调用的。
res =[callable(xfunc)for xfunc in xfuncs]print("functors callable:")print(res)"""
functors callable:
[True, True, True, True, True, True, True, True]
"""
判断函子的类型(types.XXX)。那么函子的类型并不完全相同。
res =[[isinstance(xfunc, xtype)for xtype in xtypes]for xfunc in xfuncs]## output the resultprint("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>
"""
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 the xtypes.XXX suggested by @Ryan is a better choice.
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>
"""
I draw a table of callable functor’s types using the data.
Then you can choose the functors’ types that suitable.
#check inspect.isfunction and type.FunctionTypeIn[46]: inspect.isfunction(detect_function)Out[46]:TrueIn[47]: inspect.isfunction(hasattr)Out[47]:FalseIn[48]: isinstance(detect_function, types.FunctionType)Out[48]:TrueIn[49]: isinstance(getattr, types.FunctionType)Out[49]:False#so they both just applied to judge the user-definded
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:
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.
回答 11
函数只是带有__call__方法的类,因此您可以执行
hasattr(obj,'__call__')
例如:
>>> hasattr(x,'__call__')True>>> x =2>>> hasattr(x,'__call__')False
>>>def x():...raiseTypeError...>>> hasattr(x,'__call__')True# Correct>>>try:... x()...exceptTypeError:...print"x was not callable"...
x was not callable # Wrong!
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!
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.
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()
回答 14
由于类也具有__call__方法,因此我建议另一个解决方案:
class A(object):def __init__(self):passdef __call__(self):print'I am a Class'MyClass= A()def foo():passprint hasattr(foo.__class__,'func_name')# Returns Trueprint hasattr(A.__class__,'func_name')# Returns False as expectedprint hasattr(foo,'__call__')# Returns Trueprint hasattr(A,'__call__')# (!) Returns True while it is not a function
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.
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.
How Would We Implement It
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-金
The Code Which Does It
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.
Conclusion
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!
回答 19
在Python3中,我想出了type (f) == type (lambda x:x)产生Trueif f是否为函数的结果False。但是我想我更喜欢isinstance (f, types.FunctionType),感觉不太特别。我想做type (f) is function,但这不起作用。
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.
回答 20
在先前的答复之后,我想到了这一点:
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)
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)
回答 21
您可以尝试以下方法:
if obj.__class__.__name__ in['function','builtin_function_or_method']:print('probably a function')
甚至更怪异的东西:
if"function"in lower(obj.__class__.__name__):print('probably a function')