Python中如何判断Callable对象是否为原生function类型函数
问题
是否存在可靠方案,能够区分Python中类型为 <class 'function'> 的普通函数,与其他实现了__call__方法的可调用对象?
我们需要实现一个定义如下的判断函数:
from typing import Callable def is_callable_function(obj: Callable) -> bool: ...
现有如下测试用可调用对象:
def function(*args, **kwargs): ... class CallableObj1: def __call__(self, *args, **kwargs): ... class CallableObj2: @classmethod def __call__(cls, *args, **kwargs): ... class CallableObj3: @staticmethod def __call__(*args, **kwargs): ...
要求函数运行效果符合如下预期:
>>> is_callable_function(function) True >>> is_callable_function(CallableObj1) False >>> is_callable_function(CallableObj2) False >>> is_callable_function(CallableObj3) False
目前有一个基于类型名字符串比对的实现可以达成效果,但该方案不够规范可靠:
def is_callable_function(obj: Callable) -> bool: return type(obj).__name__ == "function"
解答
使用Python标准库types模块中定义的FunctionType做类型判断即可,这是官方提供的标准方案,完全不依赖字符串匹配,行为稳定可靠。
实现代码
import types from typing import Callable def is_callable_function(obj: Callable) -> bool: return isinstance(obj, types.FunctionType)
方案说明
- 该实现直接引用Python内置的函数类型对象做判断,不存在字符串匹配方案的误判风险,在所有兼容Python标准规范的解释器实现上行为一致。
- 可以正确识别所有通过
def关键字定义的普通函数、lambda匿名函数,这两类对象的类型均为<class 'function'>,符合判断需求。 - 所有自定义可调用类的实例、可调用类本身(类为
type元类的实例)、被@classmethod/@staticmethod包装的可调用对象、内置函数、绑定/非绑定方法对象,均不属于FunctionType实例,会被正确判定为False,完全匹配预期效果。 - 如果要求必须匹配精确的
<class 'function'>类型、不识别任何继承自FunctionType的自定义子类,可以将判断逻辑替换为return type(obj) is types.FunctionType,绝大多数业务场景下使用isinstance判断即可满足需求。
补充:如果需要同时识别内置函数,可以追加判断
isinstance(obj, types.BuiltinFunctionType),但根据需求描述,本次判断仅针对<class 'function'>类型的普通函数,不需要追加该逻辑。
内容的提问来源于stack exchange,提问作者Adnan MARSO
相关产品推荐
相关产品推荐

