我有一个变量x
,我想知道它是否指向一个函数。
我希望我可以这样做:
>>> isinstance(x, function)
但这给了我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
我选择它的原因是因为
>>> 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
,除非你对函数是什么有一个非常具体的想法。
函数只是一个带有callable(x)
方法的类,所以你可以这样做
__call__
例如:
hasattr(obj, '__call__')
这是“最好”的方式,但根据你需要知道它是否可调用或注意的原因,你可以把它放在try / except块中:
>>> hasattr(x, '__call__')
True
>>> x = 2
>>> hasattr(x, '__call__')
False
如果try / except比使用try:
x()
except TypeError:
print "was not callable"
更狡猾是有争议的..我会说if hasattr(x, '__call__'): x()
更准确,因为你不会意外地捕获错误的TypeError,例如:
hasattr
以下是其他几种方式:
>>> def x():
... raise TypeError
...
>>> hasattr(x, '__call__')
True # Correct
>>> try:
... x()
... except TypeError:
... print "x was not callable"
...
x was not callable # Wrong!
这是我如何想出第二个:
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!
,你必须熟悉C++
或function object
,意思是任何可以functor
的物体。
在C ++中,be called as if it is a function
是一个函数对象,函数指针也是如此;更一般地说,定义an ordinary function
的类的对象也是如此。在C ++ 11及更高版本中,operator()
也是the lambda expression
。
相似,在Python中,那些functor
都是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
(不是可调用的类实例,或lambda表达式),那么judge whether a object is just an ordinary function or not
建议的xtypes.XXX
是更好的选择。
@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]
判断仿函数的类型(types.XXX)。然后,仿函数的类型并不完全相同。
res = [callable(xfunc) for xfunc in xfuncs]
print("functors callable:")
print(res)
"""
functors callable:
[True, True, True, True, True, True, True, True]
"""
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
方法,我建议另一种解决方案:
__call__
请注意,Python类也是可调用的。
要获取函数(以及函数,我们指的是标准函数和lambdas),请使用:
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
作为公认的答案,John Feminella表示:
检查鸭子类型物体属性的正确方法是询问它们是否嘎嘎叫,而不是看它们是否适合鸭子大小的容器。 “直接比较”方法会给许多函数提供错误的答案,比如内置函数。
尽管有两个库可以严格区分功能,但我画了一个详尽的可比较表:
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)
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',
]
至于内置函数
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
,'__call__'
等属性,而不是检查func_name
(函数不是唯一的)。这不适用于方法。
func_doc
另一种检查方法是使用>>> def x(): pass
...
>>> hasattr(x, 'func_name')
True
模块中的isfunction()
方法。
inspect
要检查对象是否是方法,请使用>>> import inspect
>>> inspect.isfunction(x)
True
无论函数是什么类,因此您可以获取实例x的类的名称并进行比较:
inspect.ismethod()
在一些答案中提到的使用
if(x.__class__.__name__ == 'function'):
print "it's a function"
和hasattr(obj, '__call__')
的解决方案有一个主要缺点:两者都使用callable(.)
方法返回类和类的实例的True
。例如。
__call__()
检查对象是否是用户定义的函数(除了那个)之外的一种正确方法是使用>>> 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
。
在Python3中,我提出了inspect — Inspect live objects,如果type (f) == type (lambda x:x)
是函数则产生True
,如果不是f
则产生False
。但我认为我更喜欢isinstance (f, types.FunctionType)
,感觉不那么特别。我想做type (f) is function
,但这不起作用。
在内置命名空间中没有构造函数的内置类型(例如函数,生成器,方法)位于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
在之前的回复之后,我想出了这个:
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")
以下是检查它的“repr方式”。它也适用于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
这对我有用:
str(type(a))=="<class 'function'>"
Since 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工具(qazxsw poi)建议:
http://docs.python.org/dev/library/2to3.html
由于import collections
isinstance(obj, collections.Callable)
,似乎选择了这个而不是hasattr(x, '__call__')
方法。
如果传递的对象可以在Python中调用,则http://bugs.python.org/issue7006将返回true,但该函数在Python 3.0中不存在,并且正确地说不会区分:
callable(x)
你会得到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
,或者首先不可调用。这对你来说可能无关紧要。
如果你想检测语法上看起来像函数的所有东西:函数,方法,内置fun / meth,lambda ......但是排除可调用对象(定义了TypeError
方法的对象),然后尝试这个:
__call__
我将它与import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))
模块中的is*()
检查代码进行了比较,上面的表达式更加完整,特别是如果您的目标是过滤掉任何函数或检测对象的常规属性。
尝试使用inspect
。