将字典作为关键字参数传递给函数

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 不,它从来都不是正确的,它使第二个始终存在问题的代码块失败。字面意思,印刷品就是一个例子。 它确实回答了这个问题,它只是没有通过字典解包来完成。根据发布的问题,他的方法完全有效。

以上是关于将字典作为关键字参数传递给函数的主要内容,如果未能解决你的问题,请参考以下文章

如何将关键字参数作为参数传递给函数?

如何将关键字对作为参数传递给函数中的模块?

将大量参数传递给 Python 函数的方法

将对象作为参数传递给函数

如何将带有 args 的成员函数作为参数传递给另一个成员函数?

C++ 将列表作为参数传递给函数