You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在运行时修改函数签名并强制执行该签名?

动态修改函数签名后如何强制执行参数校验?

你已经通过修改函数的__signature__属性成功改变了函数的签名显示,但Python解释器并不会自动基于这个属性做参数合法性校验,所以需要手动在装饰器中添加参数绑定校验逻辑。

原代码问题复现

from inspect import getfullargspec, signature
from functools import wraps

def mock(sign):
    def deco(func):
        @wraps(func)
        def wrap(*args, **kwargs):
            print('wrap', args, kwargs)
        wrap.__signature__ = signature(sign)
        return wrap
    return deco

def test(a, b):
    print(a, b)

@mock(test)
def func(c):
    print(c)

print(getfullargspec(func)) # -> FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

func(1) # -> wrap (1,) {} 未抛出异常,不符合预期

解决方案:添加参数绑定校验

利用inspect.Signature的bind方法,它会严格按照签名规则绑定参数,不符合时抛出和原生函数一致的TypeError异常。修改装饰器如下:

from inspect import getfullargspec, signature
from functools import wraps

def mock(sign):
    target_sig = signature(sign)
    def deco(func):
        @wraps(func)
        def wrap(*args, **kwargs):
            # 先执行参数绑定校验,不符合签名直接抛出异常
            bound_args = target_sig.bind(*args, **kwargs)
            # 若目标签名含默认参数,调用此方法自动填充默认值
            # bound_args.apply_defaults()
            print('wrap', bound_args.args, bound_args.kwargs)
            # 可将绑定后的参数传递给原函数执行
            # func(*bound_args.args, **bound_args.kwargs)
        wrap.__signature__ = target_sig
        return wrap
    return deco

def test(a, b):
    print(a, b)

@mock(test)
def func(c):
    print(c)

print(getfullargspec(func)) # 签名显示正常

func(1) # 抛出 TypeError: missing a required argument: 'b'
func(1, 2) # 正常输出 wrap (1, 2) {}

关键说明

  • target_sig.bind(*args, **kwargs)会严格匹配目标签名的参数规则,缺少必填参数、参数数量不符、关键字参数不匹配等场景都会抛出TypeError,和原生函数的参数校验行为完全一致。
  • 如果目标签名包含默认参数,需要调用bound_args.apply_defaults()来自动填充默认值,之后再通过bound_args.args和bound_args.kwargs获取完整的参数集合。

内容的提问来源于stack exchange,提问作者giladrv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:22:07