为何对functools.partial包装的函数调用inspect.isfunction返回False?
为什么functools.partial包装的普通函数与异步函数在inspect检测中表现不同?
现象重现
你观察到的现象确实存在:用functools.partial包装普通函数后,inspect.isfunction()返回False,但包装异步函数后inspect.iscoroutinefunction()返回True。测试代码及输出如下:
import functools import inspect def sin(a, b): print(a * b) async def asin(a, b): print(a * b) sin_partial = functools.partial(sin, 5) asin_partial = functools.partial(asin, 5) print(inspect.isfunction(sin)) print(inspect.isfunction(sin_partial)) print('----------') print(inspect.iscoroutinefunction(asin)) print(inspect.iscoroutinefunction(asin_partial))
输出:
True False ---------- True True
核心原因
1. inspect.isfunction()的判断逻辑
inspect.isfunction()仅识别原生Python函数对象(即通过def、lambda定义的function类型对象)。而functools.partial()返回的是functools.partial类的实例,并非原生函数类型,因此isfunction()会返回False。
你可以通过type(sin_partial)验证:输出为<class 'functools.partial'>,而非<class 'function'>。
2. inspect.iscoroutinefunction()的特殊处理
与isfunction()不同,iscoroutinefunction()的判断逻辑会穿透包装对象:
- 首先检查对象是否实现了协程函数特有的
__await__方法; - 若对象是包装器(比如
partial),则会通过__wrapped__属性获取被包装的原函数,再检查原函数是否为协程函数。
partial包装异步函数时会保留原函数的__wrapped__属性,因此iscoroutinefunction()能检测到内部的异步函数,返回True。
如何判断partial包装的是普通函数
如果你需要判断一个partial对象是否包装了普通函数,可以用以下方式:
# 方式1:检查__wrapped__属性指向的对象是否为函数 print(inspect.isfunction(sin_partial.__wrapped__)) # 输出True # 方式2:封装为判断函数 def is_partial_wrapped_function(obj): return isinstance(obj, functools.partial) and inspect.isfunction(obj.__wrapped__) print(is_partial_wrapped_function(sin_partial)) # 输出True
内容的提问来源于stack exchange,提问作者Flana Ban
相关产品推荐
相关产品推荐

