为什么 functools.partial 没有被检测为 types.FunctionType?

Why does functools.partial not detected as a types.FunctionType?

在我的代码中,我需要检测一个变量是否是一个函数,并对其执行一些操作。

一切顺利,直到我现在使用 functools 创建了部分函数,​​突然我的一些测试失败了:

import types
import functools

def f(s):
    print(s)

l = lambda s: print(s)

pf = functools.partial(f, 'Hello World')
pl = functools.partial(l, 'Hello World')
test_f = isinstance(f, types.FunctionType) # True
test_l = isinstance(l, types.FunctionType) # True
test_pf = isinstance(pf, types.FunctionType) # False
test_pl = isinstance(pl, types.FunctionType) # False

为什么它们之间有区别?两种变体都是可调用的...更重要的是,如果我不能使用 types.FunctionType?

,我如何检测某个变量是否是函数,即使它是部分函数

functools.partial 是一个 class 和一个 __call__ 方法,它在文档中说:

Return a new partial object which when called will behave like func

(粗体强调是我加的)

我们可以在 Python REPL 中确认这一点:

>>> from functools import partial
>>> add_one = partial(sum, 1)
>>> type(add_one)
<class 'functools.partial'>

一个 Python 等价物是这样的:

class Partial:

    def __init__(self, func, *args, **kwargs):
        self.func = func
        self.args = args
        self.kwargs = kwargs

    def __call__(self, *args, **kwargs):
        return self.func(*self.args, *args, **self.kwargs, **kwargs)

所以它围绕函数创建了一个简单的包装器对象,像这样的对象根本就不是函数。 types.FunctionType 仅适用于实际功能。

您正在寻找的是一种检查对象是否 可调用 的方法,为此您可以使用内置的 callable 函数:

>>> callable(sum)
True
>>> callable(3)
False
>>> callable(functools.partial(sum, 1))
True

在大多数情况下,您不需要知道某物是否是一个函数。通常,您只关心该对象是否 可调用 。为了检查这一点,python 有一个名为 callable.

的内置函数

请注意,仅仅因为callable returns True,并不意味着调用对象会成功。然而,对于调用函数来说同样如此 :-).


如果你真的只想处理函数和 partial 对象,那么你可以将检查写成:

isinstance(obj, (types.FunctionType, functools.partial))

但这还不够"ducky"我的口味。