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

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

>>> isinstance(x, function)

但这给了我:

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

我选这个是因为

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

当前回答

你可以DIY一个简短的函数来检查输入是否不是字符串,并将输入转换为字符串将返回匹配的名称定义:

def isFunction(o):return not isinstance(o,str) and str(o)[:3]=='<fu';

我认为这段代码已经兼容所有python版本。

或者如果有什么变化,你可以添加额外的转换为小写并检查内容长度。我看到的函数的格式字符串是“<函数”+名称+“在0xFFFFFFFF>”

其他回答

在一些答案中提到的使用hasattr(obj, '__call__')和callable(.)的解决方案有一个主要缺点:对于具有__call__()方法的类和类的实例,它们都返回True。如。

>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True

检查一个对象是否是用户定义的函数(只有a that)的一个正确方法是使用isfunction(.):

>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True

如果您需要检查其他类型,请查看inspect -检查活动对象。

下面的函数应该返回一个布尔值:

callable(x)

作为公认的答案,John Feminella说:

检查鸭子类型对象属性的正确方法是询问它们是否嘎嘎叫,而不是查看它们是否适合鸭子大小的容器。“直接比较”的方法会对许多函数给出错误的答案,比如内置函数。

尽管有两个库来严格区分函数,但我画了一个详尽的可比表:

8.9. 内置类型的动态类型创建和名称。Python 3.7.0文档

30.13. inspect -检查活动对象- Python 3.7.0文档

#import inspect             #import types
['isabstract',
 'isasyncgen',              'AsyncGeneratorType',
 'isasyncgenfunction', 
 'isawaitable',
 'isbuiltin',               'BuiltinFunctionType',
                            'BuiltinMethodType',
 'isclass',
 'iscode',                  'CodeType',
 'iscoroutine',             'CoroutineType',
 'iscoroutinefunction',
 'isdatadescriptor',
 'isframe',                 'FrameType',
 'isfunction',              'FunctionType',
                            'LambdaType',
                            'MethodType',
 'isgenerator',             'GeneratorType',
 'isgeneratorfunction',
 'ismethod',
 'ismethoddescriptor',
 'ismodule',                'ModuleType',        
 'isroutine',            
 'istraceback',             'TracebackType'
                            'MappingProxyType',
]

“duck typing”是一般用途的首选解决方案:

def detect_function(obj):
    return hasattr(obj,"__call__")

In [26]: detect_function(detect_function)
Out[26]: True
In [27]: callable(detect_function)
Out[27]: True

至于内置函数

In [43]: callable(hasattr)
Out[43]: True

当进一步检查是内置函数还是用户定义函数

#check inspect.isfunction and type.FunctionType
In [46]: inspect.isfunction(detect_function)
Out[46]: True
In [47]: inspect.isfunction(hasattr)
Out[47]: False
In [48]: isinstance(detect_function, types.FunctionType)
Out[48]: True
In [49]: isinstance(getattr, types.FunctionType)
Out[49]: False
#so they both just applied to judge the user-definded

确定是否内置函数

In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False

总结

采用可调用鸭类型检查函数, 使用类型。如果您有进一步指定的需求,请使用BuiltinFunctionType。

Python的2to3工具(http://docs.python.org/dev/library/2to3.html)建议:

import collections
isinstance(obj, collections.Callable)

这似乎是选择了hasattr(x, '__call__')方法,因为http://bugs.python.org/issue7006。

这是我的代码:

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