为何向Python的*args传入字典仅会得到键?
场景设定
假设有如下函数:
def variadic(*args, **kwargs): print("Positional:", args) print("Keyword:", kwargs)
出于测试目的,用以下方式调用该函数:
variadic({'a':5, 'b':'x'}, *{'a':4, 'b':'y'}, **{'a':3, 'b':'z'})
输出结果:
Positional: ({'a': 5, 'b': 'x'}, 'a', 'b') Keyword: {'a': 3, 'b': 'z'}
问题说明
对关键字参数的行为没有疑问,但位置参数得到的元组是({'a': 5, 'b': 'x'}, 'a', 'b')。理解第一个元素{'a': 5, 'b': 'x'}的由来,但对{'a':4, 'b':'y'}仅传入键(a、b)感到困惑,原本以为向*args传入字典会报错。
猜想分析
尚未找到确切答案,但猜测Python解析*args时会执行类似如下逻辑:
for arg in args: do something
由于直接迭代字典(而非d.items())仅会获取键,因此传入的字典被解析为键序列。希望有人证实该猜想或解释背后的原理。
原理解释
你的猜想完全正确。Python中*操作符(解包操作符)的核心作用是可迭代对象解包:当你在函数调用中使用*iterable时,Python会遍历这个可迭代对象,把其中的每个元素作为独立的位置参数传入函数。
而字典在Python中的默认迭代行为就是遍历它的键——直接对字典执行for k in dict操作时,拿到的就是所有键。所以当你写*{'a':4, 'b':'y'}时,Python会把这个字典当成可迭代对象,遍历出它的键'a'和'b',然后把这两个值作为单独的位置参数传入variadic函数,最终就出现在了args元组里。
如果想要把字典的其他内容作为位置参数传入,需要明确指定迭代对象:
- 解包键值对:用
*d.items(),会得到('a',4), ('b','y')作为位置参数 - 解包值:用
*d.values(),会得到4, 'y'作为位置参数
另外,Python允许任何可迭代对象被*解包,只要它能被for循环遍历,所以传入字典不会报错——字典本身就是合法的可迭代对象。
内容的提问来源于stack exchange,提问作者Siyana Pavlova
相关产品推荐
相关产品推荐

