Python中如何判断函数参数哪个是*args哪个是**kwargs
问题
给定一个Python函数:
def func(a, b, *c, **d): pass
我可以通过如下代码获取该函数的参数名称:
>>> print(func.__code__.co_varnames) ('a', 'b', 'c', 'd')
但我该如何判断出上述参数中,c是对应*args的可变位置参数、d是对应**kwargs的可变关键字参数呢?
解答
不要自己硬解析__code__.co_varnames做判断,Python标准库自带的inspect模块已经封装好了成熟的签名解析逻辑,兼容所有Python3的合法函数参数类型,是官方推荐的做法。
推荐方案:使用inspect.signature
直接遍历签名的参数对象,通过kind属性就能判断参数类型:
import inspect def func(a, b, *c, **d): pass sig = inspect.signature(func) for param_name, param in sig.parameters.items(): print(f"参数名:{param_name},类型:{param.kind}")
运行输出:
参数名:a,类型:POSITIONAL_OR_KEYWORD 参数名:b,类型:POSITIONAL_OR_KEYWORD 参数名:c,类型:VAR_POSITIONAL 参数名:d,类型:VAR_KEYWORD
其中和问题相关的两个类型标识:
VAR_POSITIONAL:就是*c这类接收多余位置参数的可变位置参数(也就是常说的*args)VAR_KEYWORD:就是**d这类接收多余关键字参数的可变关键字参数(也就是常说的**kwargs)
其余常见参数类型标识:
POSITIONAL_ONLY:仅限位置传参的参数(比如内置函数len的参数,不能用关键字传)KEYWORD_ONLY:仅限关键字传参的参数(定义在*args后面的普通参数)
不推荐的底层属性判断方式
如果你非要跳过inspect直接读函数代码对象的底层属性,可以通过co_flags位标记+co_varnames索引计算判断:
co = func.__code__ arg_count = co.co_argcount has_var_pos = bool(co.co_flags & 0x04) # 标记位4代表存在*args has_var_kw = bool(co.co_flags & 0x08) # 标记位8代表存在**kwargs var_pos_name = co.co_varnames[arg_count] if has_var_pos else None var_kw_name = co.co_varnames[arg_count + (1 if has_var_pos else 0)] if has_var_kw else None print(var_pos_name, var_kw_name) # 输出 c d
这个方法兼容性差,碰到仅限关键字参数、Python版本迭代调整内部属性存储逻辑时很容易算错索引,生产环境不建议使用。
内容的提问来源于stack exchange,提问作者Lazy Bum
相关产品推荐
相关产品推荐

