在函数调用和定义中都可以使用 **kwargs

6
假设我有一个函数get_data,它需要一些关键字参数。我是否可以这样做?
def get_data(arg1, **kwargs):
    print arg1, arg2, arg3, arg4

arg1 = 1
data['arg2'] = 2 
data['arg3'] = 3 
data['arg4'] = 4 

get_data(arg1, **data)

因此,这个想法是避免在函数调用和函数定义中重复输入参数名称。我使用字典作为参数调用函数,字典的键变成了函数的本地变量,它们的值是字典的值。

我尝试了上述方法,但出现了错误,显示全局名称'arg2'未定义。我明白我可以更改get_data定义中的locals()以获得所需的行为。

所以我的代码看起来像这样:

def get_data(arg1, kwargs):
    locals().update(kwargs)
    print arg1, arg2, arg3, arg4

arg1 = 1
data['arg2'] = 2 
data['arg3'] = 3 
data['arg4'] = 4 

get_data(arg1, data)

而且它也不起作用。如果没有使用locals(),我能否实现这种行为?


2
不要修改locals,因为它甚至不能保证始终正常工作:http://docs.python.org/2/library/functions.html#locals - jamylak
1
为什么你要这样做?如果你知道arg2、arg3、arg4总是会被传递,那么你应该将它们指定为单独的参数。如果你不这样做,即使你得到了期望的行为,但当你引用data没有定义的arg4时,它会引发NameError。它甚至不会打印任何数据,只会引发一个错误。 - kampu
@MorganWilde 我理解这个概念,但是想法是避免在函数定义和函数调用中写名称。 - lovesh
1
lovesh,避免在函数定义中使用名称是一个不好的概念,因为这使得理解所需参数和哪些参数没有效果变得非常困难。 - Vladimir
lovesh,是什么阻止你使用 det_data(arg1, arg2, arg3, arg4): ... 签名呢? - Vladimir
显示剩余3条评论
2个回答

11

**kwargs 是一个普通的字典。尝试这样做:

**kwargs is a plain dictionary. Try this:

def get_data(arg1, **kwargs):
    print arg1, kwargs['arg2'], kwargs['arg3'], kwargs['arg4']

此外,请查看有关关键字参数的文档。


4
如果我们看一下您的例子:
def get_data(arg1, **kwargs):
    print arg1, arg2, arg3, arg4

在您的`get_data`函数的命名空间中,有一个名为`arg1`的变量,但没有名为`arg2`的变量。所以您无法访问不在命名空间中的函数或变量。
实际上,在您的命名空间中有一个名为`arg1`的变量和一个名为`kwargs`的`dictionary`对象。在`kwargs`之前使用`**`符号(这里的名称`kwargs`并不重要,它也可以是其他名称)告诉您的Python编译器,`kwargs`是一个字典,并且该字典中的所有值都将作为命名参数在函数定义中进行评估。
让我们来看一个例子:
def myFunc(**kwargs):
    do something

myFunc(key1='mykey', key2=2)

当您使用命名参数key1key2调用myFunc时,您的函数定义就像
def myFunc(key1=None, key2=None):

但是有一个例外!由于myFunc没有命名参数,编译器不知道如何直接处理它们,因为您可以将任何命名参数传递给函数。

因此,您的函数接受这些命名参数,就像在调用函数时使用字典一样:

myFunc({key1:'mykey', key2:2})

所以,您的函数定义在一个字典中获取这些参数。 **kwargs 在那一点上定义了您的字典,这也告诉编译器任何命名的参数将被接受(通过在kwargs之前使用**符号)

def myFunc(**kwargs):
    print kwargs

将会打印

{key1:'mykey', key2:2}

在你的例子中,你可以像使用字典一样使用 kwargs

def myFunc(**kwargs):
    kwargs['arg2']
    kwargs.get('arg3')

我希望这不会很复杂(:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接