协慌网

登录 贡献 社区

如何检测 Python 变量是否为函数?

我有一个变量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.FunctionTypesinspect.isfunction方法(两者都做完全相同的事情)附带一些警告。对于非 Python 函数,它返回False例如,大多数内置函数都是用 C 而不是 Python 实现的,因此它们返回False

>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True

因此, types.FunctionType可能会给您带来令人惊讶的结果。检查鸭子型物体属性的正确方法是询问它们是否发出嘎嘎声,而不是看它们是否适合鸭子大小的容器。

内置名称空间中没有构造函数的内置类型(例如,函数,生成器,方法)位于types模块中。您可以在isinstance调用中types.FunctionType

>>> 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

从 Python 2.1 开始,您可以从inspect模块isfunction

>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True