Python运行时创建固定参数数量函数的无eval实现方法咨询
Python运行时创建固定参数数量函数的实现方案
可以实现,不需要依赖eval,通过手动为生成的组合函数绑定正确的签名即可解决参数信息丢失、无法二次组合的问题。
原实现存在的问题
- 传递参数时没有对切片后的参数元组解包,会导致
f1、f2收到的参数数量不符合预期 - 生成的
combined函数用*args接收可变参数,没有绑定真实的参数签名,inspect.signature读取时无法拿到正确的参数数量,导致二次组合失败
完整实现代码
from inspect import signature, Parameter import functools def combine(f1, f2): # 读取两个输入函数的签名 sig1 = signature(f1) sig2 = signature(f2) # 拆分参数:第一个参数是公共的x,剩下的是各自的独立参数 params1 = list(sig1.parameters.values()) x_param = params1[0] f1_custom_params = params1[1:] f1_param_count = len(f1_custom_params) params2 = list(sig2.parameters.values()) f2_custom_params = params2[1:] f2_param_count = len(f2_custom_params) # 拼接新函数的完整参数列表 new_params = [x_param] + f1_custom_params + f2_custom_params @functools.wraps(f1) def combined(x, *args): # 拆分参数分别传给两个函数 args_f1 = args[:f1_param_count] args_f2 = args[f1_param_count: f1_param_count + f2_param_count] return f1(x, *args_f1) + f2(x, *args_f2) # 为组合函数绑定正确的签名,供inspect读取 combined.__signature__ = sig1.replace(parameters=new_params) # 自定义函数名方便识别 combined.__name__ = f"{f1.__name__}_{f2.__name__}_combined" return combined
测试示例
# 测试基础组合 def f1(x, a, b): return x + a + b def f2(x, c, d, e): return x * c + d + e f_new = combine(f1, f2) # 打印参数签名验证:输出(x, a, b, c, d, e) print(signature(f_new)) # 调用验证:1+2+3 + 1*4+5+6 = 6 + 15 = 21 print(f_new(1,2,3,4,5,6)) # 测试二次组合 def f3(x, m, n): return x - m -n f_new2 = combine(f_new, f3) # 打印参数签名验证:输出(x, a, b, c, d, e, m, n) print(signature(f_new2)) # 调用验证:21 + (1 - 7 -8) = 21 -14 =7 print(f_new2(1,2,3,4,5,6,7,8))
实现原理
Python的inspect模块读取函数签名时,会优先读取函数的__signature__属性,我们手动生成正确的参数列表绑定到这个属性上,就能让组合后的函数和普通函数有完全一致的参数信息,支持任意次数的嵌套组合。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

