将字典作为关键字参数传递给函数
Posted
技术标签:
【中文标题】将字典作为关键字参数传递给函数【英文标题】:Passing a dictionary to a function as keyword parameters 【发布时间】:2010-09-24 23:32:28 【问题描述】:我想使用字典在 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)
这可能吗?
【问题讨论】:
【参考方案1】: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 的解决方案是在你的函数中接受(并忽略)额外的 kwargs(注意,按照约定,_
是一个用于被丢弃的变量名,尽管从技术上讲它只是一个有效的变量名蟒蛇):
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
位置参数和关键字参数的示例:
请注意,您可以像使用 kwargs 一样有效地使用位置参数和列表或元组,这里有一个更高级的示例,结合了位置参数和关键字参数:
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
【讨论】:
使用 print.format 解包特别有用。例如:'hello greeting name'.format( **'name': 'Andrew', 'greeting': 'Mr')
老问题,但仍然非常相关。感谢您的详细回复。您知道解决案例 3 的任何方法吗?意思是当字典中的项目多于参数时,将字典的项目映射到函数参数?
@spencer 已将解决方案添加到答案中。
@Martlark 使用template strings,会变成:subst_dict = 'name': 'Andrew','greeting': 'Mr.' title = 'hello $greeting $name' formatted_title = Template(title).substitute(**subst_dict)
【参考方案2】:
在 python 中,这称为“解包”,您可以在tutorial 中找到有关它的信息。我同意它的文档很烂,尤其是因为它非常有用。
【讨论】:
最好将链接的相关内容复制到您的答案中,而不是依靠链接存活到时间结束。 @Richard 这是一个关于网络的深刻哲学观点,我非常不同意!唉,我在这里的空白处没有空间来分享我的精彩证明...... @llimllib,那我得问问 Wiles 博士了! "它的文档很烂",除非你的问题是打印“如果你给这只鹦鹉加上 400 万伏电压,它就不会发声。E 出血' demised" 使用字典。在这种情况下,它是完美的。【参考方案3】:最后自己想通了。很简单,我只是缺少 ** 操作符来解包字典
所以我的例子变成了:
d = dict(p1=1, p2=2)
def f2(p1,p2):
print p1, p2
f2(**d)
【讨论】:
如果你想让它帮助别人,你应该改写你的问题:问题不是传递字典,你想要的是把字典变成关键字参数 值得注意的是,您还可以将列表解包为位置参数:f2(*[1,2]) “dereference”:在这个 Python 上下文中,通常的术语是“unpack”。 :) 这很棒,只需将它与 argparse/__dict__ 一起使用,就可以非常容易地将命令行参数直接解析为类对象的选项。 在将字典作为参数传递给函数时,我们想要解包字典的原因是什么?【参考方案4】:你去 - 可以工作任何其他可迭代:
d = 'param' : 'test'
def f(dictionary):
for key in dictionary:
print key
f(d)
【讨论】:
似乎人们对此表示反对,因为它回答了原始问题,而不是改写后的问题。我建议现在删除这篇文章。 @dotancohen 不,它从来都不是正确的,它使第二个始终存在问题的代码块失败。字面意思,印刷品就是一个例子。 它确实回答了这个问题,它只是没有通过字典解包来完成。根据发布的问题,他的方法完全有效。以上是关于将字典作为关键字参数传递给函数的主要内容,如果未能解决你的问题,请参考以下文章