我有一个变量x,我想知道它是否指向一个函数。
我希望我能做一些像这样的事情:
>>> isinstance(x, function)
但这给了我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
我选这个是因为
>>> type(x)
<type 'function'>
我有一个变量x,我想知道它是否指向一个函数。
我希望我能做一些像这样的事情:
>>> isinstance(x, function)
但这给了我:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
我选这个是因为
>>> type(x)
<type 'function'>
当前回答
一个精确的功能检查器
Callable是一个很好的解决方案。然而,我想用与John Feminella相反的方式来对待这个问题。不要像这样对待它:
检查鸭子类型对象属性的正确方法是询问它们是否嘎嘎叫,而不是查看它们是否适合鸭子大小的容器。“直接比较”的方法会对许多函数给出错误的答案,比如内置函数。
我们会这样对待它:
判断一个东西是不是鸭子的正确方法不是看它会不会嘎嘎叫,而是通过几个过滤器来判断它是否真的是一只鸭子,而不是仅仅从表面上看它是否像一只鸭子。
我们将如何实现它
'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]
一个false是is_function(partial),因为那是一个类,而不是一个函数,而这正是函数,而不是类。下面是一个预览,您可以从中试用代码。
结论
Callable (obj)是检查对象是否是函数的首选方法,如果您想通过鸭子类型检查绝对值。
我们的自定义is_function(obj),如果你没有将任何可调用的类实例作为函数,而只是内置或lambda, def或partial定义的函数,那么可能经过一些编辑后,它是检查对象是否是函数的首选方法。
我想这就是全部内容了。祝你有愉快的一天!
其他回答
被接受的答案在当时被认为是正确的。因为它 结果是,没有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中的一个bug。也就是说, 没有比这更准确的结果了 结果比使用callable()本身,因为typeobject->tp_call 槽方法不能以任何其他方式访问。
只需使用callable()
如果传递的对象可以在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,还是一开始就不可调用。这对你来说可能无关紧要。
一个精确的功能检查器
Callable是一个很好的解决方案。然而,我想用与John Feminella相反的方式来对待这个问题。不要像这样对待它:
检查鸭子类型对象属性的正确方法是询问它们是否嘎嘎叫,而不是查看它们是否适合鸭子大小的容器。“直接比较”的方法会对许多函数给出错误的答案,比如内置函数。
我们会这样对待它:
判断一个东西是不是鸭子的正确方法不是看它会不会嘎嘎叫,而是通过几个过滤器来判断它是否真的是一只鸭子,而不是仅仅从表面上看它是否像一只鸭子。
我们将如何实现它
'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]
一个false是is_function(partial),因为那是一个类,而不是一个函数,而这正是函数,而不是类。下面是一个预览,您可以从中试用代码。
结论
Callable (obj)是检查对象是否是函数的首选方法,如果您想通过鸭子类型检查绝对值。
我们的自定义is_function(obj),如果你没有将任何可调用的类实例作为函数,而只是内置或lambda, def或partial定义的函数,那么可能经过一些编辑后,它是检查对象是否是函数的首选方法。
我想这就是全部内容了。祝你有愉快的一天!
你可以DIY一个简短的函数来检查输入是否不是字符串,并将输入转换为字符串将返回匹配的名称定义:
def isFunction(o):return not isinstance(o,str) and str(o)[:3]=='<fu';
我认为这段代码已经兼容所有python版本。
或者如果有什么变化,你可以添加额外的转换为小写并检查内容长度。我看到的函数的格式字符串是“<函数”+名称+“在0xFFFFFFFF>”
你可以试试这个:
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')