我有一个变量,x我想知道它是否指向一个函数.
我希望我可以这样做:
>>> isinstance(x, function)
Run Code Online (Sandbox Code Playgroud)
但这给了我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
Run Code Online (Sandbox Code Playgroud)
我选择它的原因是因为
>>> type(x)
<type 'function'>
Run Code Online (Sandbox Code Playgroud)
Joh*_*lla 816
如果这适用于Python 2.x或Python 3.2+,您也可以使用callable().它曾经被弃用,但现在已经过时,所以你可以再次使用它.你可以在这里阅读讨论:http://bugs.python.org/issue10518.你可以这样做:
callable(obj)
Run Code Online (Sandbox Code Playgroud)
如果这是针对Python 3.x但是在3.2之前,请检查该对象是否具有__call__属性.你可以这样做:
hasattr(obj, '__call__')
Run Code Online (Sandbox Code Playgroud)
经常提出的types.FunctionTypes方法是不正确的,因为它无法涵盖许多你可能希望它通过的情况,比如内置:
>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True
Run Code Online (Sandbox Code Playgroud)
检查鸭子类型物体属性的正确方法是询问它们是否嘎嘎叫,而不是看它们是否适合鸭子大小的容器.types.FunctionType除非你对函数的含义有一个非常具体的了解,否则不要使用.
Rya*_*yan 250
内建类型没有在内置的命名空间构造函数(如函数发生器,方法)是在types模块.您可以types.FunctionType在isinstance调用中使用.
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
Run Code Online (Sandbox Code Playgroud)
Pao*_*olo 87
从Python 2.1开始,您可以isfunction从inspect模块导入.
>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True
Run Code Online (Sandbox Code Playgroud)
Sin*_*ion 69
接受的答案是在提供被认为是正确的时候.事实证明,有无可替代为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
Run Code Online (Sandbox Code Playgroud)
我们可以通过__call__从班级中移除一把猴子扳手.只是为了让事情更加令人兴奋,__call__为实例添加假货!
>>> del Spam.__call__
>>> can_o_spam.__call__ = lambda *args: 'OK?'
Run Code Online (Sandbox Code Playgroud)
请注意,这真的不可调用:
>>> can_o_spam()
Traceback (most recent call last):
...
TypeError: 'Spam' object is not callable
Run Code Online (Sandbox Code Playgroud)
callable() 返回正确的结果:
>>> callable(can_o_spam)
False
Run Code Online (Sandbox Code Playgroud)
但是hasattr是错误的:
>>> hasattr(can_o_spam, '__call__')
True
Run Code Online (Sandbox Code Playgroud)
can_o_spam毕竟确实有这个属性; 它只是在调用实例时才使用.
更加微妙,isinstance()也是错误的:
>>> isinstance(can_o_spam, collections.Callable)
True
Run Code Online (Sandbox Code Playgroud)
因为我们之前使用过此检查,后来删除了该方法,因此abc.ABCMeta
缓存了结果.可以说这是一个错误abc.ABCMeta.这就是说,有真的也没有可能的方式可能会产生更准确的结果比结果比使用callable()本身,因为typeobject->tp_call
槽的方法是不以任何其他方式使用.
只是用 callable()
小智 38
| 可调用(x) | hasattr(x, \'__call__\') | 检查.isfunction(x) | 检查.ismethod(x) | 检查.isgeneratorfunction(x) | 检查.iscoroutinefunction(x) | 检查.isasyncgenfunction(x) | isinstance(x, 打字.Callable) | isinstance(x, types.BuiltinFunctionType) | isinstance(x, types.BuiltinMethodType) | isinstance(x, 类型.FunctionType) | isinstance(x, 类型.MethodType) | isinstance(x, 类型.LambdaType) | isinstance(x, functools.partial) | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 打印 | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 |
| 功能 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
| functools.partial | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a |
| <拉姆达> | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
| 发电机 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
| 异步函数 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
| 异步生成器 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
| A | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 |
| 冰毒 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
| 类方法 | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 |
| 静态方法 | \xe2\x88\x9a | \xe2\x88\x9a | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 | \xe2\x88\x9a | \xc3\x97 |
import types\nimport inspect\nimport functools\nimport typing\n\n\ndef judge(x):\n name = x.__name__ if hasattr(x, \'__name__\') else \'functools.partial\'\n print(name)\n print(\'\\ttype({})={}\'.format(name, type(x)))\n print(\'\\tcallable({})={}\'.format(name, callable(x)))\n print(\'\\thasattr({}, \\\'__call__\\\')={}\'.format(name, hasattr(x, \'__call__\')))\n print()\n print(\'\\tinspect.isfunction({})={}\'.format(name, inspect.isfunction(x)))\n print(\'\\tinspect.ismethod({})={}\'.format(name, inspect.ismethod(x)))\n print(\'\\tinspect.isgeneratorfunction({})={}\'.format(name, inspect.isgeneratorfunction(x)))\n print(\'\\tinspect.iscoroutinefunction({})={}\'.format(name, inspect.iscoroutinefunction(x)))\n print(\'\\tinspect.isasyncgenfunction({})={}\'.format(name, inspect.isasyncgenfunction(x)))\n print()\n print(\'\\tisinstance({}, typing.Callable)={}\'.format(name, isinstance(x, typing.Callable)))\n print(\'\\tisinstance({}, types.BuiltinFunctionType)={}\'.format(name, isinstance(x, types.BuiltinFunctionType)))\n print(\'\\tisinstance({}, types.BuiltinMethodType)={}\'.format(name, isinstance(x, types.BuiltinMethodType)))\n print(\'\\tisinstance({}, types.FunctionType)={}\'.format(name, isinstance(x, types.FunctionType)))\n print(\'\\tisinstance({}, types.MethodType)={}\'.format(name, isinstance(x, types.MethodType)))\n print(\'\\tisinstance({}, types.LambdaType)={}\'.format(name, isinstance(x, types.LambdaType)))\n print(\'\\tisinstance({}, functools.partial)={}\'.format(name, isinstance(x, functools.partial)))\n\n\ndef func(a, b):\n pass\n\n\npartial = functools.partial(func, a=1)\n\n_lambda = lambda _: _\n\n\ndef generator():\n yield 1\n yield 2\n\n\nasync def async_func():\n pass\n\n\nasync def async_generator():\n yield 1\n\n\nclass A:\n def __call__(self, a, b):\n pass\n\n def meth(self, a, b):\n pass\n\n @classmethod\n def classmeth(cls, a, b):\n pass\n\n @staticmethod\n def staticmeth(a, b):\n pass\n\n\nfor func in [print,\n func,\n partial,\n _lambda,\n generator,\n async_func,\n async_generator,\n A,\n A.meth,\n A.classmeth,\n A.staticmeth]:\n judge(func)\nRun Code Online (Sandbox Code Playgroud)\n选择最常用的三种方法\xef\xbc\x9a
\n\n| 次/秒 | |
|---|---|
| 可调用(x) | 0.86 |
| hasattr(x, \'__call__\') | 1.36 |
| isinstance(x, 打字.Callable) | 12.19 |
import typing\nfrom timeit import timeit\n\n\ndef x():\n pass\n\n\ndef f1():\n return callable(x)\n\n\ndef f2():\n return hasattr(x, \'__call__\')\n\n\ndef f3():\n return isinstance(x, typing.Callable)\n\n\nprint(timeit(f1, number=10000000))\nprint(timeit(f2, number=10000000))\nprint(timeit(f3, number=10000000))\n# 0.8643081\n# 1.3563508\n# 12.193492500000001\nRun Code Online (Sandbox Code Playgroud)\n
Nik*_*iah 37
以下应该返回一个布尔值:
callable(x)
Run Code Online (Sandbox Code Playgroud)
nh2*_*nh2 25
Python的2to3工具(http://docs.python.org/dev/library/2to3.html)建议:
import collections
isinstance(obj, collections.Callable)
Run Code Online (Sandbox Code Playgroud)
hasattr(x, '__call__')由于http://bugs.python.org/issue7006,似乎选择了这个而不是方法.
Chr*_* B. 19
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)
Run Code Online (Sandbox Code Playgroud)
你会得到<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
Run Code Online (Sandbox Code Playgroud)
当然,这不会告诉您它是否可调用但TypeError在执行时抛出,或者首先不可调用.这对你来说可能无关紧要.
Mar*_*ski 14
如果你想检测语法上看起来像函数的所有东西:函数,方法,内置fun/meth,lambda ......但是排除可调用对象(__call__定义方法的对象),然后尝试这个:
import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))
Run Code Online (Sandbox Code Playgroud)
我将其与模块中的is*()检查代码进行inspect了比较,上面的表达式更为完整,特别是如果您的目标是过滤掉任何函数或检测对象的常规属性.
callable是一个非常好的解决方案。然而,我想以与约翰·费米内拉相反的方式来对待这个问题。而不是像这样说:
\n\n\n检查鸭子类型对象属性的正确方法是询问它们是否嘎嘎叫,而不是看它们是否适合鸭子大小的容器。对于许多函数(例如内置函数),“直接比较”方法会给出错误的答案。
\n
我们会这样对待它:
\n\n\n判断一个东西是否是鸭子的正确方法不是看它是否会嘎嘎叫,而是通过几个过滤器看看它是否真的是一只鸭子,而不是仅仅从表面上看它是否是一只鸭子。
\n
“types”模块有很多类来检测函数,最有用的是types.FunctionType,但还有很多其他类,例如方法类型、内置类型和 lambda 类型。我们还将把“functools.partial”对象视为一个函数。
\n我们检查它是否是函数的简单方法是对所有这些类型使用 isinstance 条件。以前,我想创建一个继承上述所有类的基类,但我无法做到这一点,因为Python不允许我们继承上述某些类。
\n下面是哪些类可以对哪些函数进行分类的表格:
\n
\n以上函数表由 kinght-\xe9\x87\x91 提供
现在,这是完成我们上面描述的所有工作的代码。
\nfrom types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, LambdaType\nfrom functools import partial\n\ndef is_function(obj):\n return isinstance(obj, (BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, LambdaType, partial))\n\n#-------------------------------------------------\n\ndef my_func():\n pass\n\ndef add_both(x, y):\n return x + y\n\nclass a:\n def b(self):\n pass\n\ncheck = [\n\nis_function(lambda x: x + x),\nis_function(my_func),\nis_function(a.b),\nis_function(partial),\nis_function(partial(add_both, 2))\n\n]\n\nprint(check)\n>>> [True, True, True, False, True]\nRun Code Online (Sandbox Code Playgroud)\n一个错误是 is_function(partial),因为那是一个类,而不是一个函数,而这正是函数,而不是类。这是供您试用代码的预览。
\n如果您想通过鸭子类型而不是绝对值来检查对象是否是函数,则 callable(obj)是检查对象是否为函数的首选方法。
\n我们的自定义is_function(obj),也许经过一些编辑是检查对象是否是函数的首选方法,如果您不将任何可调用类实例计数为函数,而仅将内置函数或使用lambda定义的函数,def或部分.
\n我认为这就是全部了。祝你有美好的一天!
\n这是另外两种方式:
def isFunction1(f) :
return type(f) == type(lambda x: x);
def isFunction2(f) :
return 'function' in str(type(f));
Run Code Online (Sandbox Code Playgroud)
这是我想到的第二种方法:
>>> type(lambda x: x);
<type 'function'>
>>> str(type(lambda x: x));
"<type 'function'>"
# Look Maa, function! ... I ACTUALLY told my mom about this!
Run Code Online (Sandbox Code Playgroud)
函数只是带有__call__方法的类,因此您可以执行
hasattr(obj, '__call__')
Run Code Online (Sandbox Code Playgroud)
例如:
>>> hasattr(x, '__call__')
True
>>> x = 2
>>> hasattr(x, '__call__')
False
Run Code Online (Sandbox Code Playgroud)
这是“最佳”方法,但是根据您为什么需要知道它是否可调用或注释的原因,您可以将其放在try / execpt块中:
try:
x()
except TypeError:
print "was not callable"
Run Code Online (Sandbox Code Playgroud)
如果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!
Run Code Online (Sandbox Code Playgroud)
如果您已经学过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
Run Code Online (Sandbox Code Playgroud)
定义一个类和一个普通函数。
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)
Run Code Online (Sandbox Code Playgroud)
定义函子:
#(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
Run Code Online (Sandbox Code Playgroud)
定义函子列表和类型列表:
## 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]
Run Code Online (Sandbox Code Playgroud)
判断函子是否可调用。如您所见,它们都是可调用的。
res = [callable(xfunc) for xfunc in xfuncs]
print("functors callable:")
print(res)
"""
functors callable:
[True, True, True, True, True, True, True, True]
"""
Run Code Online (Sandbox Code Playgroud)
判断函子的类型(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>
"""
Run Code Online (Sandbox Code Playgroud)
然后,您可以选择合适的函子类型。
如:
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
Run Code Online (Sandbox Code Playgroud)
作为公认的答案,约翰·费米内拉说:
检查鸭子型物体属性的正确方法是询问它们是否发出嘎嘎声,而不是看它们是否适合鸭子大小的容器。“直接比较”方法将对许多功能(例如内置函数)给出错误的答案。
即使有两个库严格区分功能,我还是绘制了一个详尽的可比较表:
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',
]
Run Code Online (Sandbox Code Playgroud)
“鸭式打字”是通用的首选解决方案:
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
Run Code Online (Sandbox Code Playgroud)
至于内建函数
In [43]: callable(hasattr)
Out[43]: True
Run Code Online (Sandbox Code Playgroud)
再走一步检查内置功能或用户定义的功能
#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
Run Code Online (Sandbox Code Playgroud)
确定是否 builtin function
In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False
Run Code Online (Sandbox Code Playgroud)
摘要
采用callable鸭式检查功能,如果您有进一步指定的需求,
请使用types.BuiltinFunctionType。