问题:通过** kwargs将** kwargs参数传递给另一个函数
我不理解以下示例,可以说我具有以下功能:
# python likes
def save(filename, data, **kwargs):
fo = openX(filename, "w", **kwargs) # <- #1
fo.write(data)
fo.close()
# python doesnt like
def save2(filename, data, **kwargs):
fo = openX(filename, "w", kwargs) # <- #2
fo.write(data)
fo.close()
def openX(filename, mode, **kwargs):
#doing something fancy and returning a file object
为什么#1是正确的解决方案,而#2是错误的解决方案?**kwargs
基本上是一个字典,所以如果我想将参数传递给openX,我认为正确的方法是没有**
并且只给出字典。但是python显然不喜欢第二个,并告诉我我给了3个而不是2个参数。那么,这背后的原因是什么呢?
I do not understand the following example, lets say I have these functions:
# python likes
def save(filename, data, **kwargs):
fo = openX(filename, "w", **kwargs) # <- #1
fo.write(data)
fo.close()
# python doesnt like
def save2(filename, data, **kwargs):
fo = openX(filename, "w", kwargs) # <- #2
fo.write(data)
fo.close()
def openX(filename, mode, **kwargs):
#doing something fancy and returning a file object
Why is #1 the right solution and #2 the wrong one? **kwargs
is basically a dict, so If I want to pass down the argument to openX I think the correct way would be without **
and just giving the dict. But python obviously doesnt like the second one and tells me I gave 3 instead of 2 arguments.
So whats the reason behind this?
回答 0
在第二个示例中,您提供3个参数:文件名,模式和字典(kwargs
)。但是Python期望:2个形式参数加上关键字参数。
通过给字典加上“ **”前缀,可以打开字典的包装 kwargs
为关键字参数。
字典(类型 dict
)是包含键值对的单个变量。
“关键字参数”是键值方法参数。
通过**
在函数调用期间添加前缀,可以将任何字典解压缩为关键字参数。
In the second example you provide 3 arguments: filename, mode and a dictionary (kwargs
). But Python expects: 2 formal arguments plus keyword arguments.
By prefixing the dictionary by ‘**’ you unpack the dictionary kwargs
to keywords arguments.
A dictionary (type dict
) is a single variable containing key-value pairs.
“Keyword arguments” are key-value method-parameters.
Any dictionary can by unpacked to keyword arguments by prefixing it with **
during function call.
回答 1
该**
语法告诉Python来收集关键字参数到一个字典。所述save2
被传递下来作为非关键字参数(一个字典对象)。在openX
没有看到任何关键字参数,因此**args
不会习惯。相反,它得到了第三个非关键字参数(字典)。要解决该问题,请更改openX
函数的定义。
def openX(filename, mode, kwargs):
pass
The **
syntax tells Python to collect keyword arguments into a dictionary. The save2
is passing it down as a non-keyword argument (a dictionary object). The openX
is not seeing any keyword arguments so the **args
doesn’t get used. It’s instead getting a third non-keyword argument (the dictionary). To fix that change the definition of the openX
function.
def openX(filename, mode, kwargs):
pass
回答 2
扩展@gecco的答案,以下是一个示例,将向您显示差异:
def foo(**kwargs):
for entry in kwargs.items():
print("Key: {}, value: {}".format(entry[0], entry[1]))
# call using normal keys:
foo(a=1, b=2, c=3)
# call using an unpacked dictionary:
foo(**{"a": 1, "b":2, "c":3})
# call using a dictionary fails because the function will think you are
# giving it a positional argument
foo({"a": 1, "b": 2, "c": 3})
# this yields the same error as any other positional argument
foo(3)
foo("string")
在这里,您可以查看解压缩字典的工作方式,以及发送实际字典失败的原因
Expanding on @gecco ‘s answer, the following is an example that’ll show you the difference:
def foo(**kwargs):
for entry in kwargs.items():
print("Key: {}, value: {}".format(entry[0], entry[1]))
# call using normal keys:
foo(a=1, b=2, c=3)
# call using an unpacked dictionary:
foo(**{"a": 1, "b":2, "c":3})
# call using a dictionary fails because the function will think you are
# giving it a positional argument
foo({"a": 1, "b": 2, "c": 3})
# this yields the same error as any other positional argument
foo(3)
foo("string")
Here you can see how unpacking a dictionary works, and why sending an actual dictionary fails
回答 3
因为字典是单个值。如果要将关键字扩展作为一组关键字参数传递,则需要使用关键字扩展。
Because a dictionary is a single value. You need to use keyword expansion if you want to pass it as a group of keyword arguments.
回答 4