将字典作为关键字参数传递给函数
我想在Python中调用一个函数,使用一个字典来传递参数,字典里的键值对要对应上函数的参数。
这里有一段代码:
d = dict(param='test')
def f(param):
print(param)
f(d)
这段代码打印出来的是 {'param': 'test'}
,但我希望它只打印 test
。
我希望它能对更多的参数也这样工作:
d = dict(p1=1, p2=2)
def f2(p1, p2):
print(p1, p2)
f2(d)
这样做可以吗?
4 个回答
36
在Python中,这个过程叫做“解包”。你可以在这个教程里找到一些相关的信息。我同意它的文档写得不太好,尤其是考虑到这个功能是多么有用。
217
In[1]: def myfunc(a=1, b=2):
In[2]: print(a, b)
In[3]: mydict = {'a': 100, 'b': 200}
In[4]: myfunc(**mydict)
100 200
这里有一些额外的细节,可能对你理解这个问题有帮助(这是我在阅读后产生的一些疑问,并进行了测试):
- 这个函数可以有一些参数,这些参数不在字典里
- 你不能覆盖已经在字典里的函数参数
- 字典不能包含函数里没有的值。
例子:
例子 1:函数可以有一些参数,这些参数不在字典里
In[5]: mydict = {'a': 100}
In[6]: myfunc(**mydict)
100 2
例子 2:你不能覆盖已经在字典里的函数参数
In[7]: mydict = {'a': 100, 'b': 200}
In[8]: myfunc(a=3, **mydict)
TypeError: myfunc() got multiple values for keyword argument 'a'
例子 3:字典不能有函数里没有的值。
In[9]: mydict = {'a': 100, 'b': 200, 'c': 300}
In[10]: myfunc(**mydict)
TypeError: myfunc() got an unexpected keyword argument 'c'
如何使用一个包含比函数参数更多键的字典:
解决上面第3点的方法是,在你的函数中接受(并忽略)额外的关键字参数(注意,按照惯例,_
是用来表示被丢弃的变量名,虽然从技术上讲,它只是Python中的一个有效变量名):
In[11]: def myfunc2(a=None, **_):
In[12]: print(a)
In[13]: mydict = {'a': 100, 'b': 200, 'c': 300}
In[14]: myfunc2(**mydict)
100
另一种选择是根据函数中可用的关键字参数来过滤字典:
In[15]: import inspect
In[16]: mydict = {'a': 100, 'b': 200, 'c': 300}
In[17]: filtered_mydict = {k: v for k, v in mydict.items() if k in [p.name for p in inspect.signature(myfunc).parameters.values()]}
In[18]: myfunc(**filtered_mydict)
100 200
包含位置参数和关键字参数的例子:
注意,你可以像使用关键字参数一样使用位置参数和列表或元组,这里有一个更复杂的例子,结合了位置参数和关键字参数:
In[19]: def myfunc3(a, *posargs, b=2, **kwargs):
In[20]: print(a, b)
In[21]: print(posargs)
In[22]: print(kwargs)
In[23]: mylist = [10, 20, 30]
In[24]: mydict = {'b': 200, 'c': 300}
In[25]: myfunc3(*mylist, **mydict)
10 200
(20, 30)
{'c': 300}
729
最后我自己搞明白了。其实很简单,我只是忘了用 ** 这个符号来展开字典。
所以我的例子变成了:
d = dict(p1=1, p2=2)
def f2(p1,p2):
print(p1, p2)
f2(**d)