如何用inspect.signature检查函数仅需一个位置参数?
运行时校验函数是否可接受单个位置参数
问题背景
需要在运行时校验传入的函数是否可以接受单个位置参数(该参数为字符串,函数返回真值)。最初的实现通过检查参数数量是否为1来判断,但无法兼容支持*args和**kwargs的函数——这类函数明明可以正常接收1个位置参数,却被误判为不合法。
初始实现代码:
from inspect import signature from typing import Callable def check(v_in : Callable): """check that the function can be called with 1 positional parameter supplied""" sig = signature(v_in) len_param = len(sig.parameters) if not len_param == 1: raise ValueError( f"expecting 1 parameter, of type `str` for {v_in}. got {len_param}" ) return v_in
解决方案
方法1:利用inspect.signature.bind做实际参数绑定校验
这是最直接可靠的方法,直接模拟调用时的参数绑定逻辑,只要能成功绑定单个位置参数,就说明函数符合要求,无需手动分析参数类型。
from inspect import signature def check(v_in): """校验函数是否可接受单个位置参数调用""" sig = signature(v_in) try: # 尝试绑定一个测试字符串作为位置参数 sig.bind("test_input") except TypeError as e: raise ValueError(f"函数 {v_in} 无法接受单个位置参数调用:{e}") from e return v_in
这个方法能覆盖所有合法场景:
- 单参数函数(
def f(a): ...) - 带
*args的函数(def f(*args): ...) - 含默认值参数的函数(
def f(a=None): ...) - 混合参数但可接受单个位置参数的函数(
def f(a, *args): ...)
同时会正确拦截非法场景:
- 需要多个必填位置参数的函数(
def f(a, b): ...) - 仅支持关键字参数的函数(
def f(*, a): ...)
方法2:手动分析参数类型与必填性
如果需要更精细的控制,可以通过遍历参数的kind属性和默认值,判断函数是否满足要求:
from inspect import signature, Parameter def check(v_in): sig = signature(v_in) params = list(sig.parameters.values()) required_positional = 0 has_var_positional = False has_positional_slot = False for param in params: if param.kind in (Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD): has_positional_slot = True # 统计无默认值的必填位置参数 if param.default is Parameter.empty: required_positional += 1 elif param.kind == Parameter.VAR_POSITIONAL: has_var_positional = True # 无任何可接收位置参数的途径(全关键字参数) if not has_positional_slot and not has_var_positional: raise ValueError(f"函数 {v_in} 无法接收任何位置参数") # 必填位置参数超过1个,无法仅传单个位置参数调用 if required_positional > 1: raise ValueError(f"函数 {v_in} 至少需要 {required_positional} 个位置参数,不符合要求") return v_in
关于typing.Protocol的说明
Protocol是用于静态类型检查的工具,Python运行时不会强制校验函数是否符合Protocol定义,因此无法直接用它做运行时的参数校验。如果需要结合类型提示和运行时校验,可以考虑第三方库,但标准库层面无法实现。
内容的提问来源于stack exchange,提问作者JL Peyret
相关产品推荐
相关产品推荐

