我有一个变量x,我想知道它是否指向一个函数。

我希望我能做一些像这样的事情:

>>> isinstance(x, function)

但这给了我:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'function' is not defined

我选这个是因为

>>> type(x)
<type 'function'>

当前回答

根据之前的回复,我想出了这个:

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)

其他回答

在内置命名空间中没有构造函数的内置类型(例如函数、生成器、方法)在types模块中。你可以使用类型。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)

和随机的。Shuffle(技术上是一种隐藏随机的方法。随机实例):

>>> type(random.shuffle), isinstance(random.shuffle, types.FunctionType)
(<class 'method'>, False)

如果你在做一些特定类型的事情。FunctionType实例,如反编译字节码或检查闭包变量,使用类型。FunctionType,但如果你只是需要一个对象像函数一样可调用,请使用callable。

一个精确的功能检查器

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定义的函数,那么可能经过一些编辑后,它是检查对象是否是函数的首选方法。

我想这就是全部内容了。祝你有愉快的一天!

函数只是一个带有__call__方法的类,所以你可以这样做

hasattr(obj, '__call__')

例如:

>>> hasattr(x, '__call__')
True

>>> x = 2
>>> hasattr(x, '__call__')
False

这是“最好”的方法,但这取决于你为什么需要知道它是可调用的还是注释的,你可以把它放在try/execpt块中:

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!

根据之前的回复,我想出了这个:

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)

注意,Python类也是可调用的。

要获得函数(这里的函数指的是标准函数和lambdas),请使用:

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)