如何检测变量是否是函数?
- 2025-02-08 08:52:00
- admin 原创
- 47
问题描述:
我有一个变量x
,,我想知道它是否指向一个函数。
我曾希望我能做类似的事情:
>>> isinstance(x, function)
但这让我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
我之所以选择它是因为
>>> type(x)
<type 'function'>
解决方案 1:
如果这是针对 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
或inspect.isfunction
方法(两者的作用完全相同)有很多注意事项。它返回False
非 Python 函数。例如,大多数内置函数False
都是用 C 而不是 Python 实现的,因此它们返回:
>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True
sotypes.FunctionType
可能会给你带来意想不到的结果。检查鸭子类型对象的属性的正确方法是询问它们是否会嘎嘎叫,而不是看它们是否适合放在鸭子大小的容器中。
解决方案 2:
内置命名空间中没有构造函数的内置类型(例如函数、生成器、方法)位于模块中types
。您可以types.FunctionType
在isinstance
调用中使用:
>>> import types
>>> types.FunctionType
<class 'function'>
>>> def f(): pass
>>> isinstance(f, types.FunctionType)
True
>>> isinstance(lambda x : None, types.FunctionType)
True
请注意,这使用了一个非常具体的“函数”概念,通常不是您所需要的。例如,它拒绝zip
(技术上是一个类):
>>> type(zip), isinstance(zip, types.FunctionType)
(<class 'type'>, False)
open
(内置函数具有不同类型):
>>> type(open), isinstance(open, types.FunctionType)
(<class 'builtin_function_or_method'>, False)
和random.shuffle
(技术上是隐藏实例的方法random.Random
):
>>> type(random.shuffle), isinstance(random.shuffle, types.FunctionType)
(<class 'method'>, False)
如果您正在对实例执行某些特定操作types.FunctionType
,例如反编译其字节码或检查闭包变量,请使用types.FunctionType
,但如果您只需要一个像函数一样可调用的对象,请使用callable
。
解决方案 3:
从 Python 2.1 开始,isfunction
您可以从模块导入inspect
。
>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True
解决方案 4:
接受的答案是正确的。事实证明,在 Python 3.2 中没有替代品:具体来说,检查被测试对象的字段。没有简单的 Python 等效项。大多数建议的测试在大多数情况下都是正确的:callable()
`callable()`tp_call
>>> 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
slot 方法无法通过任何其他方式访问。
只需使用callable()
解决方案 5:
以下应该返回一个布尔值:
callable(x)
解决方案 6:
结果
可调用(x) | hasattr(x,'__call__') | 检查.isfunction(x) | 检查.ismethod(x) | 检查.isgenerator函数(x) | 检查.iscoroutine函数(x) | 检查.isasyncgen函数(x) | isinstance(x,打字。可调用) | isinstance(x,类型。BuiltinFunctionType) | isinstance(x,类型。BuiltinMethodType) | isinstance(x,类型。FunctionType) | isinstance(x,类型。方法类型) | isinstance(x,类型.LambdaType) | isinstance(x,functools.partial) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
打印 | √ | √ | × | × | × | × | × | √ | √ | √ | × | × | × | × |
函数 | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
函数工具.partial | √ | √ | × | × | × | × | × | √ | × | × | × | × | × | √ |
<lambda> | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
发电机 | √ | √ | √ | × | √ | × | × | √ | × | × | √ | × | √ | × |
异步函数 | √ | √ | √ | × | × | √ | × | √ | × | × | √ | × | √ | × |
异步生成器 | √ | √ | √ | × | × | × | √ | √ | × | × | √ | × | √ | × |
一个 | √ | √ | × | × | × | × | × | √ | × | × | × | × | × | × |
冰毒 | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
类方法 | √ | √ | × | √ | × | × | × | √ | × | × | × | √ | × | × |
静态方法 | √ | √ | √ | × | × | × | × | √ | × | × | √ | × | √ | × |
import types
import inspect
import functools
import typing
def judge(x):
name = x.__name__ if hasattr(x, '__name__') else 'functools.partial'
print(name)
print(' type({})={}'.format(name, type(x)))
print(' callable({})={}'.format(name, callable(x)))
print(' hasattr({}, \'__call__\')={}'.format(name, hasattr(x, '__call__')))
print()
print(' inspect.isfunction({})={}'.format(name, inspect.isfunction(x)))
print(' inspect.ismethod({})={}'.format(name, inspect.ismethod(x)))
print(' inspect.isgeneratorfunction({})={}'.format(name, inspect.isgeneratorfunction(x)))
print(' inspect.iscoroutinefunction({})={}'.format(name, inspect.iscoroutinefunction(x)))
print(' inspect.isasyncgenfunction({})={}'.format(name, inspect.isasyncgenfunction(x)))
print()
print(' isinstance({}, typing.Callable)={}'.format(name, isinstance(x, typing.Callable)))
print(' isinstance({}, types.BuiltinFunctionType)={}'.format(name, isinstance(x, types.BuiltinFunctionType)))
print(' isinstance({}, types.BuiltinMethodType)={}'.format(name, isinstance(x, types.BuiltinMethodType)))
print(' isinstance({}, types.FunctionType)={}'.format(name, isinstance(x, types.FunctionType)))
print(' isinstance({}, types.MethodType)={}'.format(name, isinstance(x, types.MethodType)))
print(' isinstance({}, types.LambdaType)={}'.format(name, isinstance(x, types.LambdaType)))
print(' isinstance({}, functools.partial)={}'.format(name, isinstance(x, functools.partial)))
def func(a, b):
pass
partial = functools.partial(func, a=1)
_lambda = lambda _: _
def generator():
yield 1
yield 2
async def async_func():
pass
async def async_generator():
yield 1
class A:
def __call__(self, a, b):
pass
def meth(self, a, b):
pass
@classmethod
def classmeth(cls, a, b):
pass
@staticmethod
def staticmeth(a, b):
pass
for func in [print,
func,
partial,
_lambda,
generator,
async_func,
async_generator,
A,
A.meth,
A.classmeth,
A.staticmeth]:
judge(func)
时间
选择最常见的三种方法:
callable(x)
hasattr(x, '__call__')
isinstance(x, typing.Callable)
时间/秒 | |
---|---|
可调用(x) | 0.86 |
hasattr(x,'__call__') | 1.36 |
isinstance(x,打字。可调用) | 12.19 |
import typing
from timeit import timeit
def x():
pass
def f1():
return callable(x)
def f2():
return hasattr(x, '__call__')
def f3():
return isinstance(x, typing.Callable)
print(timeit(f1, number=10000000))
print(timeit(f2, number=10000000))
print(timeit(f3, number=10000000))
# 0.8643081
# 1.3563508
# 12.193492500000001
解决方案 7:
Python 的 2to3 工具(http://docs.python.org/dev/library/2to3.html)建议:
import collections
isinstance(obj, collections.Callable)
看来由于hasattr(x, '__call__')
http://bugs.python.org/issue7006而选择了这种方法。
解决方案 8:
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)
您将获得<class 'A'> True
和<type function> True
作为输出。
isinstance
可以很好地确定某个东西是否为函数(try isinstance(b, types.FunctionType)
);如果您真的想知道某个东西是否可以调用,您可以使用它hasattr(b, '__call__')
或者直接尝试它。
test_as_func = True
try:
b()
except TypeError:
test_as_func = False
except:
pass
当然,这不会告诉您它是否可调用,但TypeError
在执行时会抛出一个,或者首先不可调用。这对您来说可能并不重要。
解决方案 9:
尝试使用callable(x)
。
摘抄:
如果对象参数看起来可调用,则返回 True,否则返回 False。
解决方案 10:
如果你想检测语法上看起来像函数的所有内容:函数,方法,内置的 fun/meth,lambda ...但排除可调用对象(__call__
定义了方法的对象),那么尝试这个:
import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))
is*()
我将其与模块中的检查代码进行了比较inspect
,上面的表达式更加完整,特别是如果您的目标是过滤掉任何函数或检测对象的常规属性。
解决方案 11:
如果你学过C++
,你一定熟悉function object
或functor
,指的是任何可以的物体be called as if it is a function
。
在 C++ 中, an ordinary function
是函数对象, 也是函数指针;更一般地, 是定义 的类的对象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
建议的@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] <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
解决方案 12:
作为公认的答案,John Feminella 指出:
检查鸭子类型对象的属性的正确方法是询问它们是否会嘎嘎叫,而不是看它们是否适合鸭子大小的容器。对于许多函数(如内置函数),“直接比较”方法会给出错误的答案。
虽然有两个库可以严格区分功能,但我还是绘制了一个详尽的可比较表格:
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
解决方案 13:
精确功能检查器
callable是一个很好的解决方案。但是,我想用与 John Feminella 相反的方式来处理这个问题。而不是像这样处理它:
检查鸭子类型对象的属性的正确方法是询问它们是否会嘎嘎叫,而不是看它们是否适合鸭子大小的容器。对于许多函数(如内置函数),“直接比较”方法会给出错误的答案。
我们将这样处理:
判断一只动物是不是鸭子的正确方法不是看它是否会嘎嘎叫,而是要通过几个过滤来判断它是否真的是鸭子,而不是只从表面上看它是否像鸭子。
我们如何实现它
“types”模块有很多类可以检测函数,最有用的是types.FunctionType,但也有很多其他的,比如方法类型、内置类型和 lambda 类型。我们还将把“functools.partial”对象视为一个函数。
我们检查它是否是函数的简单方法是对所有这些类型使用 isinstance 条件。以前,我想创建一个继承自上述所有类型的基类,但我无法做到这一点,因为 Python 不允许我们从上述某些类继承。
下面是一个表格,说明哪些类别可以对哪些功能进行分类:
以上功能表由 kinght-金提供
执行此操作的代码
现在,这是完成我们上面描述的所有工作的代码。
from types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, LambdaType
from functools import partial
def is_function(obj):
return isinstance(obj, (BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, LambdaType, partial))
#-------------------------------------------------
def my_func():
pass
def add_both(x, y):
return x + y
class a:
def b(self):
pass
check = [
is_function(lambda x: x + x),
is_function(my_func),
is_function(a.b),
is_function(partial),
is_function(partial(add_both, 2))
]
print(check)
>>> [True, True, True, False, True]
唯一的错误是 is_function(partial),因为这是一个类,而不是一个函数,而这正是函数,而不是类。以下是供您试用代码的预览。
结论
如果您想通过鸭子类型而不是绝对类型来检查对象是否为函数,则callable(obj)是首选方法。
如果您不将任何可调用类实例算作函数,而只将内置函数、lambda、def或partial 定义的函数算作函数,那么我们自定义的is_function(obj)或许经过一些编辑是检查对象是否为函数的首选方法。
我想这就结束了。祝您有美好的一天!
解决方案 14:
以下是其他几种方法:
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!
解决方案 15:
函数只是一个带有__call__
方法的类,因此你可以这样做
hasattr(obj, '__call__')
例如:
>>> hasattr(x, '__call__')
True
>>> x = 2
>>> hasattr(x, '__call__')
False
这是“最佳”做法,但取决于您为什么需要知道它是否可调用或注意,您可以将它放在 try/exect 块中:
try:
x()
except TypeError:
print "was not callable"
有争议的是,try/except 是否比 doing if hasattr(x, '__call__'): x()
. 更具 Python 风格。我会说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!
解决方案 16:
'__call__'
您可以检查用户定义函数是否具有属性func_name
、等,而不必检查(这不仅限于函数)。func_doc
但这对方法不起作用。
>>> def x(): pass
...
>>> hasattr(x, 'func_name')
True
另一种检查方式是使用模块isfunction()
中的方法inspect
。
>>> import inspect
>>> inspect.isfunction(x)
True
要检查对象是否是方法,请使用inspect.ismethod()
解决方案 17:
由于类也有__call__
方法,因此我推荐另一种解决方案:
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
解决方案 18:
请注意,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)
解决方案 19:
无论什么函数都是一个类,因此您可以取实例 x 的类的名称并进行比较:
if(x.__class__.__name__ == 'function'):
print "it's a function"
解决方案 20:
一些答案中使用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
如果您需要检查其他类型,请查看检查——检查活动对象。
解决方案 21:
在 Python3 中,我想出了如果是函数则type (f) == type (lambda x:x)
返回结果,如果不是则返回结果。但我想我更喜欢,感觉不那么临时。我想做,但那行不通。True
`fFalse
isinstance (f, types.FunctionType)`type (f) is function
解决方案 22:
你可以尝试这个:
if obj.__class__.__name__ in ['function', 'builtin_function_or_method']:
print('probably a function')
甚至一些更奇怪的事情:
if "function" in lower(obj.__class__.__name__):
print('probably a function')
解决方案 23:
结合@Sumukh Barve、@Katsu 和@tinnick 的答案,如果你的动机只是为了获取控制台中可供你使用的内置函数列表,那么这两个选项有效:
[i for i, j in __builtin__.__dict__.items() if j.__class__.__name__ in ['function', 'builtin_function_or_method']]
[i for i, j in __builtin__.__dict__.items() if str(j)[:18] == '<built-in function']
解决方案 24:
这是我的代码:
# -*- coding: utf-8 -*-
import hashlib
import inspect
# calc everything to md5!!
def count_md5(content):
if isinstance(content, dict):
return count_md5(
[(str(k), count_md5(content[k])) for k in sorted(content.keys())],
)
elif isinstance(content, (list, tuple)):
content = [count_md5(k) for k in content]
elif callable(content):
return make_callable_hash(content)
return calc_md5(str(content))
def calc_md5(content):
m2 = hashlib.md5()
if isinstance(content, str):
m2.update(content.encode("utf8"))
else:
m2.update(content)
return m2.hexdigest()
def make_callable_hash(content):
if inspect.isclass(content):
h = []
for attr in [i for i in sorted(dir(content)) if not i.startswith("__")]:
v = getattr(content, attr)
h.append(count_md5(v))
return calc_md5("".join(h))
return calc_md5(content.__name__)
对于callable,我们很多时候只是想看看属性的值是否一致,所以我们可以把所有的属性都取下来callable
,然后求值。
如果是类,callable会返回true,所以不是很严谨
解决方案 25:
根据之前的回复,我得出了以下结论:
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)
解决方案 26:
使用下面两个 Python 内置函数isinstance()和type(),您可以检查它是否是一个函数,因此无需导入任何内容:
def test():
pass
print(isinstance(test, type(test)))
输出:
True
解决方案 27:
def myfunc():
x = 1
print(isinstance(myfunc, type(lambda x:x)))
注意,这lambda x:x
是获取函数类型并进行比较的默认函数
解决方案 28:
如果值可调用时代码将继续执行调用,则只需执行调用并捕获TypeError
。
def myfunc(x):
try:
x()
except TypeError:
raise Exception("Not callable")
解决方案 29:
以下是检查它的“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
解决方案 30:
这对我有用:
str(type(a))=="<class 'function'>"