如何检测一个pythonvariables是否是一个函数?
我有一个variables, x
,我想知道它是否指向一个函数。
我本来希望能做到这样的事情:
>>> isinstance(x, function)
但是那给了我:
Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'function' is not defined
我select的原因是因为
>>> type(x) <type 'function'>
如果是Python 2.x或Python 3.2+,那么也可以使用callable()
。 它曾经被弃用,但现在不赞成,所以你可以再次使用它。 你可以阅读这里的讨论: http : //bugs.python.org/issue10518 。 你可以这样做:
callable(obj)
如果这是针对Python 3.x,但在3.2之前,请检查该对象是否具有__call__
属性。 你可以这样做:
hasattr(obj, '__call__')
经常提出的types.FunctionTypes
方法是不正确的,因为它不能涵盖许多你可能希望它通过的情况,就像内置函数一样:
>>> isinstance(open, types.FunctionType) False >>> callable(open) True
检查鸭型物品的正确方法是询问他们是否嘎嘎,而不是看他们是否适合装鸭子的容器。 不要使用types.FunctionType
除非你对函数是什么有一个非常具体的概念。
内build命名空间中没有构造函数的内buildtypes(如函数,生成器,方法)位于types
模块中。 您可以在isinstance调用中使用types.FunctionType
。
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
从Python 2.1开始,您可以从inspect
模块导入isfunction
。
>>> from inspect import isfunction >>> def f(): pass >>> isfunction(f) True >>> isfunction(lambda x: x) True
被接受的答案在当时被认为是正确的; 事实certificate,在python 3.2中没有可替代的callable()
:具体来说, callable()
检查被testing对象的tp_call
字段。 没有普通的python等价物。 大部分build议的testing大部分时间都是正确的:
>>> 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
我们可以通过从课堂上删除__call__
来将猴子扳手扔进去。 只是为了让事情更激动人心,添加一个假的__call__
实例!
>>> del Spam.__call__ >>> can_o_spam.__call__ = lambda *args: 'OK?'
注意这真的不可调用:
>>> can_o_spam() Traceback (most recent call last): ... TypeError: 'Spam' object is not callable
callable()
返回正确的结果:
>>> callable(can_o_spam) False
但hasattr
是错误的 :
>>> hasattr(can_o_spam, '__call__') True
can_o_spam
具有该属性,它只是在调用实例时不使用。
更微妙的是, isinstance()
也会出错:
>>> isinstance(can_o_spam, collections.Callable) True
因为我们先用这个检查,后来删除了这个方法, abc.ABCMeta
caching结果。 可以说这是abc.ABCMeta
一个bug。 也就是说,除了使用callable()
本身之外,真的没有办法产生比结果更精确的结果,因为typeobject->tp_call
slot方法不能以任何其他方式访问。
只需使用callable()
以下应该返回一个布尔值:
callable(x)
Python的2to3工具( http://docs.python.org/dev/library/2to3.html )build议:
import collections isinstance(obj, collections.Callable)
看起来这是因为http://bugs.python.org/issue7006而不是;hasattr(x, '__call__')
方法。
如果传入的对象可以在Python中callable(x)
将返回true,但该函数在Python 3.0中不存在,正确地说,不会区分:
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)
你会得到<class 'A'> True
和<type function> True
作为输出。
isinstance
很好地工作,以确定是否是一个函数(尝试isinstance(b, types.FunctionType)
); 如果你真的有兴趣知道是否可以调用某个东西,你可以使用hasattr(b, '__call__')
或者只是尝试一下。
test_as_func = True try: b() except TypeError: test_as_func = False except: pass
这当然不会告诉你它是否可调用,但在执行时抛出一个TypeError
,或者一开始就不可调用。 这对你来说可能没有关系。
如果要检测语法上看起来像函数的所有内容:函数,方法,内置fun / meth,lambda …但排除可调用对象(定义了__call__
方法的对象),请尝试下面的方法:
import types isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))
我将它与inspect
模块中的is*()
检查代码进行了比较,上面的expression式更加完整,特别是如果您的目标是筛选出任何函数或检测到对象的常规属性。
尝试使用callable(x)
。
由于类也有__call__
方法,我build议另一种解决scheme:
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
函数只是一个带__call__
方法的类,所以你可以做
hasattr(obj, '__call__')
例如:
>>> hasattr(x, '__call__') True >>> x = 2 >>> hasattr(x, '__call__') False
这是做到这一点的“最佳”方法,但是根据你为什么需要知道它是否可调用或注意,你可以把它放在try / execpt块中:
try: x() except TypeError: print "was not callable"
这是有争议的,如果尝试/除了更Python'y比做if hasattr(x, '__call__'): x()
__call__ if hasattr(x, '__call__'): x()
..我会说hasattr
是更准确的,因为你不会意外地捕捉到错误的TypeError,例如:
>>> def x(): ... raise TypeError ... >>> hasattr(x, '__call__') True # Correct >>> try: ... x() ... except TypeError: ... print "x was not callable" ... x was not callable # Wrong!
您可以检查用户定义的函数是否具有func_name
, func_doc
等属性,而不是检查'__call__'
(这不是函数的专有函数)。这对于方法不起作用。
>>> def x(): pass ... >>> hasattr(x, 'func_name') True
另一种检查方式是使用inspect
模块中的isfunction()
方法。
>>> import inspect >>> inspect.isfunction(x) True
要检查对象是否是方法,请使用inspect.ismethod()
以下是其他几种方法:
def isFunction1(f) : return type(f) == type(lambda x: x); def isFunction2(f) : return 'function' in str(type(f));
下面是我想到第二个:
>>> type(lambda x: x); <type 'function'> >>> str(type(lambda x: x)); "<type 'function'>" # Look Maa, function! ... I ACTUALLY told my mom about this!
请注意,Python类也是可调用的。
要获得函数(和函数,我们指的是标准函数和lambda)使用:
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)
无论函数是什么类,所以你可以采取实例x的类的名称和比较:
if(x.__class__.__name__ == 'function'): print "it's a function"
在某些答案中提到的使用hasattr(obj, '__call__')
和callable(.)
的解决scheme有一个主要缺点:它们都使用__call__()
方法返回类和实例类的True
。 例如。
>>> import collections >>> Test = collections.namedtuple('Test', []) >>> callable(Test) True >>> hasattr(Test, '__call__') True
检查一个对象是否是一个用户定义的函数(而不是一个)的一个正确方法是使用isfunction(.)
:
>>> import inspect >>> inspect.isfunction(Test) False >>> def t(): pass >>> inspect.isfunction(t) True
如果你需要检查其他types,看看检查 – 检查活物 。
在Python3中,我想出了type (f) == type (lambda x:x)
,如果f
是一个函数,则返回True
否则返回False
。 但我认为我更喜欢isinstance (f, types.FunctionType)
,这感觉不太专门。 我想做type (f) is function
,但是这不起作用。
之前的回复之后,我想出了这个:
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)
如果代码将继续执行调用,如果值是可调用的,只需执行调用并捕获TypeError
。
def myfunc(x): try: x() except TypeError: raise Exception("Not callable")