如何静态覆盖函数参数并保留正确的类型提示与文档字符串?
解决方案:创建固定参数的偏函数并保留原函数特性
问题背景
现有函数original,包含指定参数、类型注解及文档字符串。需要定义函数new,本质调用original但固定参数a为A_DEFAULT,要求:
new的签名为原函数移除参数a后的形式(即(b: str))- 保留原函数的文档字符串
- 签名和文档能在IDE中正常显示,且无需手动复制原函数的签名与文档
方法1:自定义装饰器 + functools.wraps + 签名修改
通过自定义装饰器固定目标参数,利用functools.wraps继承原函数文档,再通过inspect模块修改函数签名。
import functools import inspect A_DEFAULT = 10 def original(a: int, b: str): "description" return str(a) + b def fix_first_arg(default_val): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): return func(default_val, *args, **kwargs) # 修改签名:移除第一个参数a sig = inspect.signature(func) params = list(sig.parameters.values())[1:] new_sig = sig.replace(parameters=params) wrapper.__signature__ = new_sig return wrapper return decorator new = fix_first_arg(A_DEFAULT)(original)
说明:
functools.wraps自动同步原函数的__doc__、__name__等属性- 修改
__signature__后,IDE能直接识别移除参数后的签名 - 调用
new(x)完全等价于original(A_DEFAULT, x)
方法2:functools.partial + 手动调整属性
functools.partial快速创建偏函数,手动补充文档和签名属性以满足要求:
import functools import inspect A_DEFAULT = 10 def original(a: int, b: str): "description" return str(a) + b new = functools.partial(original, A_DEFAULT) # 继承原函数文档 new.__doc__ = original.__doc__ # 修改签名 sig = inspect.signature(original) params = list(sig.parameters.values())[1:] new.__signature__ = sig.replace(parameters=params) # 优化IDE显示:设置函数名 new.__name__ = "new"
说明:
functools.partial直接绑定固定参数,逻辑简洁- 手动复制文档和修改签名,确保IDE识别正确
- 代码量少,适合快速实现
方法3:types.FunctionType构造新函数
直接构造新函数,同步原函数关键属性并调整签名:
import types import inspect import functools A_DEFAULT = 10 def original(a: int, b: str): "description" return str(a) + b def new_func(b): return original(A_DEFAULT, b) # 同步原函数文档和类型注解 new_func.__doc__ = original.__doc__ new_func.__annotations__ = {k: v for k, v in original.__annotations__.items() if k != "a"} # 修改签名 sig = inspect.signature(original) params = list(sig.parameters.values())[1:] new_func.__signature__ = sig.replace(parameters=params) # 可选:同步更多原函数属性 functools.wraps(original)(new_func) new = new_func
说明:
- 手动定义调用逻辑,灵活性高
- 过滤类型注解,确保类型检查工具正常工作
- 可自定义扩展更多函数属性
方法4:可调用类实现(非常规方法)
通过类模拟函数行为,自定义签名和文档:
import inspect import functools A_DEFAULT = 10 def original(a: int, b: str): "description" return str(a) + b class PartialFunc: def __init__(self, func, fixed_arg): self.func = func self.fixed_arg = fixed_arg # 继承原函数文档 self.__doc__ = func.__doc__ # 修改签名 sig = inspect.signature(func) params = list(sig.parameters.values())[1:] self.__signature__ = sig.replace(parameters=params) def __call__(self, *args, **kwargs): return self.func(self.fixed_arg, *args, **kwargs) new = PartialFunc(original, A_DEFAULT)
说明:
- 类的
__call__方法实现函数调用逻辑 - 初始化时直接设置
__doc__和__signature__,IDE可识别 - 适合需要扩展额外功能的场景
内容的提问来源于stack exchange,提问作者FamousSnake
相关产品推荐
相关产品推荐

