我有一个变量x,我想知道它是否指向一个函数。
我希望我能做一些像这样的事情:
>>> isinstance(x, function)
但这给了我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
我选这个是因为
>>> type(x)
<type 'function'>
我有一个变量x,我想知道它是否指向一个函数。
我希望我能做一些像这样的事情:
>>> isinstance(x, function)
但这给了我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
我选这个是因为
>>> type(x)
<type 'function'>
当前回答
你可以检查用户定义的函数是否具有func_name、func_doc等属性,而不是检查'__call__'(它不是函数独有的)。这对方法不起作用。
>>> def x(): pass
...
>>> hasattr(x, 'func_name')
True
另一种检查方法是使用inspect模块中的isfunction()方法。
>>> import inspect
>>> inspect.isfunction(x)
True
要检查对象是否是方法,请使用inspect.ismethod()
其他回答
在一些答案中提到的使用hasattr(obj, '__call__')和callable(.)的解决方案有一个主要缺点:对于具有__call__()方法的类和类的实例,它们都返回True。如。
>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True
检查一个对象是否是用户定义的函数(只有a that)的一个正确方法是使用isfunction(.):
>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True
如果您需要检查其他类型,请查看inspect -检查活动对象。
如果你学过c++,你一定熟悉函数对象或函子,这意味着任何可以像函数一样调用的对象。
在c++中,普通函数是函数对象,函数指针也是;更一般地说,定义operator()的类的对象也是。在c++ 11及以上版本中,lambda表达式也是函子。
相似的是,在Python中,这些函子都是可调用的。一个普通的函数可以被调用,一个lambda表达式可以被调用,一个函数。Partial可以被调用,具有__call__()方法的类的实例可以被调用。
好,回到问题:我有一个变量x,我想知道它是否指向一个函数。
如果你想判断对象是否像一个函数,那么@John Feminella建议的callable方法是可以的。 如果您想判断一个对象是否只是一个普通函数(不是一个可调用的类实例或lambda表达式),那么xtypes。@Ryan建议的XXX是更好的选择。
然后我用这些代码做了一个实验:
#!/usr/bin/python3
# 2017.12.10 14:25:01 CST
# 2017.12.10 15:54:19 CST
import functools
import types
import pprint
定义一个类和一个普通函数。
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)
定义函子:
#(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 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>
"""
我用这些数据绘制了一个可调用函子类型的表。
然后你可以选择合适的函子类型。
如:
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
尝试使用callable(x)。
摘录:
如果对象参数显示为可调用,则返回True,否则返回False。
注意,Python类也是可调用的。
要获得函数(这里的函数指的是标准函数和lambdas),请使用:
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)
Python的2to3工具(http://docs.python.org/dev/library/2to3.html)建议:
import collections
isinstance(obj, collections.Callable)
这似乎是选择了hasattr(x, '__call__')方法,因为http://bugs.python.org/issue7006。