通过** kwargs将** kwargs参数传递给另一个函数


152

我不理解以下示例,可以说我具有以下功能:

# 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个参数。那么,这背后的原因是什么呢?

python 

5
我想知道为什么**args在代码中调用它。这可能是最糟糕的名称,因为人们会与它混淆*args
John La Rooy

1
好吧,我从来没有真正使用* args,所以我使用** args ^^,但是我可以修改它。

Answers:


155

在第二个示例中,您提供3个参数:文件名,模式和字典(kwargs)。但是Python期望:2个形式参数加上关键字参数。

通过给字典加上“ **”前缀,可以打开字典的包装 kwargs为关键字参数。

字典(类型 dict)是包含键值对的单个变量。

“关键字参数”是键值方法参数。

通过**在函数调用期间添加前缀,可以将任何字典解压缩为关键字参数。


5
现在我懂了。我认为关键字和字典是同一回事。

13
“任何字典都可以在函数调用期间通过在其前面加上**来扩展为关键字。” <-多数民众赞成在凉

1
另请参见:Python文档的关键字参数拆包参数列表
恐龙

8
一个实际的代码示例将使这个答案更加清晰。
OrangeDog

12

**语法告诉Python来收集关键字参数到一个字典。所述save2被传递下来作为非关键字参数(一个字典对象)。在openX没有看到任何关键字参数,因此**args不会习惯。相反,它得到了第三个非关键字参数(字典)。要解决该问题,请更改openX函数的定义。

def openX(filename, mode, kwargs):
    pass

谢谢,但是我也想使用openX而不保存,所以我必须坚持使用关键字。我以为传递关键字与传递字典基本相同,但直到现在我还不知道:)

@xMRW它们不可能是同一件事,因为您也可以将字典作为参数传递给任何函数。那么您的#1是正确的。
基思2012年

8

扩展@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")

在这里,您可以查看解压缩字典的工作方式,以及发送实际字典失败的原因


1

因为字典是单个值。如果要将关键字扩展作为一组关键字参数传递,则需要使用关键字扩展。


抱歉,什么是“关键字扩展”?你的意思是我应该使用dict_var而不是** args,而只是使用def func(argument,dict_var = 0)... func(1,{1:“ a”,2:“ b”})

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.