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

132 python

我不明白下面的例子,假设我有这些功能:

# 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
Run Code Online (Sandbox Code Playgroud)

为什么#1是正确的解决方案而#2是错误的解决方案?**kwargs基本上是一个字典,所以如果我想将参数传递给openX,我认为正确的方法是没有**,只是给dict.但是python显然不喜欢第二个并且告诉我我给了3而不是2个参数.那么这背后的原因是什么?

gec*_*cco 134

在第二个示例中,您提供了3个参数:filename,mode和dictionary(kwargs).但Python期望:2个正式参数加上关键字参数.

通过'**'为字典加前缀,可以将字典解压缩kwargs到关键字参数.

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

"关键字参数"是键值方法参数.

任何字典都可以通过**在函数调用期间为其添加前缀来解压缩到关键字参数.

  • "任何字典都可以通过在函数调用期间用**作为前缀来扩展为关键字." < - 多酷的 (9认同)
  • 现在我懂了.我认为关键词和词典是一回事. (5认同)
  • 一个实际的代码示例将使这个答案更加清晰. (5认同)

Red*_*ssi 14

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

Run Code Online (Sandbox Code Playgroud)

在这里您可以看到解压字典的工作原理,以及为什么发送实际字典会失败


Kei*_*ith 9

**语法告诉Python来收集关键字参数到一个字典.所述save2被传递下来作为非关键字参数(一个字典对象).在openX没有看到任何关键字参数,因此**args不会习惯.它取而代之的是获得第三个非关键字参数(字典).修复该更改openX函数的定义.

def openX(filename, mode, kwargs):
    pass
Run Code Online (Sandbox Code Playgroud)