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

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

>>> isinstance(x, function)

但这给了我:

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

我选这个是因为

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

当前回答

这是我的代码:

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

其他回答

函数只是一个带有__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!

如果传递的对象可以在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,还是一开始就不可调用。这对你来说可能无关紧要。

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

如果这是针对Python 2。对于Python 3.2+,可以使用callable()。它曾经被弃用,但现在不弃用了,所以您可以再次使用它。你可以在这里阅读讨论:http://bugs.python.org/issue10518。你可以这样做:

callable(obj)

如果这是针对Python 3。X但在3.2之前,检查对象是否有__call__属性。你可以这样做:

hasattr(obj, '__call__')

经常被提及的类型。函数类型或检查。Isfunction方法(两者做的是完全相同的事情)有一些注意事项。对于非python函数,它返回False。例如,大多数内置函数是用C而不是Python实现的,因此它们返回False:

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

所以类型。FunctionType可能会给您带来令人惊讶的结果。检查鸭子类型对象属性的正确方法是询问它们是否嘎嘎叫,而不是查看它们是否适合鸭子大小的容器。

在Python3中,我提出了type (f) == type (lambda x:x),如果f是一个函数,则输出True,如果不是则输出False。但我想我更喜欢isinstance (f, types.FunctionType),它感觉不那么特别。我想写type (f) is function,但这行不通。