我有一个变量,x
我想知道它是否指向一个函数.
我希望我可以这样做:
>>> isinstance(x, function)
但这给了我:
Traceback (most recent call last):
File "", line 1, in ?
NameError: name 'function' is not defined
我选择它的原因是因为
>>> type(x)
John Feminel.. 816
如果这适用于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
除非你对函数的含义有一个非常具体的了解,否则不要使用.
如果这适用于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
除非你对函数的含义有一个非常具体的了解,否则不要使用.
内建类型没有在内置的命名空间构造函数(如函数发生器,方法)是在types
模块.您可以types.FunctionType
在isinstance调用中使用.
In [1]: import types In [2]: types.FunctionType Out[2]: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开始,您可以isfunction
从inspect
模块导入.
>>> from inspect import isfunction >>> def f(): pass >>> isfunction(f) True >>> isfunction(lambda x: x) True
接受的答案是在提供被认为是正确的时候.事实证明,有无可替代为callable()
,这是背面在Python 3.2:具体地,callable()
检查tp_call
被测试的对象的字段.没有简单的Python等价物.大多数建议的测试在大多数情况下都是正确的:
>>> 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
缓存了结果.可以说这是一个错误abc.ABCMeta
.这就是说,有真的也没有可能的方式可能会产生更准确的结果比结果比使用callable()
本身,因为typeobject->tp_call
槽的方法是不以任何其他方式使用.
只是用 callable()
以下应该返回一个布尔值:
callable(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,似乎选择了这个而不是方法.
callable(x)
如果传递的对象可以在Python中调用,则返回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)
你会得到
并
作为输出.
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))
我将其与模块中的is*()
检查代码进行inspect
了比较,上面的表达式更为完整,特别是如果您的目标是过滤掉任何函数或检测对象的常规属性.
尝试使用callable(x)
.
这是另外两种方式:
def isFunction1(f) : return type(f) == type(lambda x: x); def isFunction2(f) : return 'function' in str(type(f));
这是我想到的第二种方法:
>>> type(lambda x: x);>>> str(type(lambda x: x)); " " # Look Maa, function! ... I ACTUALLY told my mom about this!
函数只是带有__call__
方法的类,因此您可以执行
hasattr(obj, '__call__')
例如:
>>> hasattr(x, '__call__') True >>> x = 2 >>> hasattr(x, '__call__') False
这是“最佳”方法,但是根据您为什么需要知道它是否可调用或注释的原因,您可以将其放在try / execpt块中:
try: x() except TypeError: print "was not callable"
如果try / except比使用Python更有意义,那是有争议的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!
如果您已经学过C++
,则必须熟悉function object
或functor
,意味着可以的任何对象be called as if it is a function
。
在C ++中, an ordinary function
是一个函数对象,一个函数指针也是如此;更一般而言,define的类的对象也是如此operator()
。在C ++ 11和更高版本中the lambda expression
也是functor
如此。
相似,在Python中,这些functors
都是callable
。An ordinary function
可以调用,a lambda expression
可以调用,可以调用,functional.partial
可以调用的实例class with a __call__() method
。
好的,回到问题: I have a variable, x, and I want to know whether it is pointing to a function or not.
如果要判断天气,对象的作用就像一个函数,则
callable
建议的方法@John Feminella
还可以。如果要
judge whether a object is just an ordinary function or not
(不是可调用的类实例或lambda表达式),则xtypes.XXX
建议使用by@Ryan
是更好的选择。
#!/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][False, True, False, True, False] [False, True, False, True, False] at 0x7f1b5081fd08> [False, False, False, False, True] functools.partial( , b=4) [False, False, False, False, False] <__main__.A object at 0x7f1b50870cc0> [False, True, False, True, False] [False, False, True, False, False] > [False, True, False, True, False] """
然后,您可以选择合适的函子类型。
如:
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
作为公认的答案,约翰·费米内拉说:
检查鸭子型物体属性的正确方法是询问它们是否发出嘎嘎声,而不是看它们是否适合鸭子大小的容器。“直接比较”方法将对许多功能(例如内置函数)给出错误的答案。
即使有两个库严格区分功能,我还是绘制了一个详尽的可比较表:
8.9。类型-动态类型创建和内置类型的名称-Python 3.7.0文档
30.13。inspect —检查活动对象— Python 3.7.0文档
#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', ]
“鸭式打字”是通用的首选解决方案:
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
至于内建函数
In [43]: callable(hasattr) Out[43]: True
再走一步检查内置功能或用户定义的功能
#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
确定是否 builtin function
In [50]: isinstance(getattr, types.BuiltinFunctionType) Out[50]: True In [51]: isinstance(detect_function, types.BuiltinFunctionType) Out[51]: False
摘要
采用callable
鸭式检查功能,如果您有进一步指定的需求,
请使用types.BuiltinFunctionType
。