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

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

>>> isinstance(x, function)

但这给了我:

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

我选这个是因为

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

当前回答

如果你想检测所有语法上看起来像函数的东西:函数、方法、内置的fun/meth、lambda…但排除可调用对象(定义了__call__方法的对象),然后尝试这个:

import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))

我将其与inspect模块中的is*()检查代码进行了比较,上面的表达式要完整得多,特别是如果您的目标是过滤任何函数或检测对象的常规属性。

其他回答

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

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中调用,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,还是一开始就不可调用。这对你来说可能无关紧要。

如果值是可调用的,代码将继续执行调用,只需执行调用并捕获TypeError。

def myfunc(x):
  try:
    x()
  except TypeError:
    raise Exception("Not callable")

这是我的代码:

# -*- 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,所以它不是很严格

使用isinstance()和type(),它们都是Python中的内置函数,你可以检查它是否是一个函数,这样你就不需要导入任何东西:

def test():
    pass

print(isinstance(test, type(test)))

输出:

True