Python 使用**kwargs时关键字参数有多个值

Python 使用**kwargs时关键字参数有多个值,python,keyword-argument,Python,Keyword Argument,函数_mget_搜索定义如下: def _mget_search(query, with_scores=False, count=False, record_term=True, **kwargs): 此函数使用关键字参数调用 _mget_search(**search_kwargs) In [1]: def fun1(a, b, c): ...: print('Passed arguments: a={} b={} c={}'.format(a, b, c)) ...

函数_mget_搜索定义如下:

def _mget_search(query, with_scores=False, count=False, record_term=True,
**kwargs): 
此函数使用关键字参数调用

_mget_search(**search_kwargs)
In [1]: def fun1(a, b, c):
   ...:     print('Passed arguments: a={} b={} c={}'.format(a, b, c))
   ...:     

In [2]: def fun2(*args):
   ...:     print('Passed args: {}'.format(args))
   ...: 

In [3]: fun1(1, 2, 3)
Passed arguments: a=1 b=2 c=3

In [4]: fun2(1, 2, 3)
Passed args: (1, 2, 3)

In [5]: fun2([1, 2, 3])
Passed args: ([1, 2, 3],)

In [6]: fun2(*[1, 2, 3])
Passed args: (1, 2, 3)

In [7]: fun1(*[1, 2, 3])
Passed arguments: a=1 b=2 c=3
函数参数搜索包含如下内容:

{'count': False, 'min_score': 20, 'end': 49, 'with_scores': False, 'start': 0, 'query': u'ouuuuu', 'max_score': inf, 'record_term': True}
我得到了这个错误-

_mget_search() got multiple values for keyword argument 'query'

我无法理解为什么会发生这种情况,以及如何纠正它。

这是因为你正在解压你试图传递的论点。尝试使用:

_mget_search(search_kwargs)
编辑

让我们深入探讨这个问题。我们将定义两个函数,并查看它们在传递各种参数时的行为

_mget_search(**search_kwargs)
In [1]: def fun1(a, b, c):
   ...:     print('Passed arguments: a={} b={} c={}'.format(a, b, c))
   ...:     

In [2]: def fun2(*args):
   ...:     print('Passed args: {}'.format(args))
   ...: 

In [3]: fun1(1, 2, 3)
Passed arguments: a=1 b=2 c=3

In [4]: fun2(1, 2, 3)
Passed args: (1, 2, 3)

In [5]: fun2([1, 2, 3])
Passed args: ([1, 2, 3],)

In [6]: fun2(*[1, 2, 3])
Passed args: (1, 2, 3)

In [7]: fun1(*[1, 2, 3])
Passed arguments: a=1 b=2 c=3

在第三次调用中,我们分别传递了3个参数,这与调用未打包列表时使用第七次调用的情况相同。将其与调用
fun2
时的情况进行比较。

这是因为您正在解压要传递的参数。尝试使用:

_mget_search(search_kwargs)
编辑

让我们深入探讨这个问题。我们将定义两个函数,并查看它们在传递各种参数时的行为

_mget_search(**search_kwargs)
In [1]: def fun1(a, b, c):
   ...:     print('Passed arguments: a={} b={} c={}'.format(a, b, c))
   ...:     

In [2]: def fun2(*args):
   ...:     print('Passed args: {}'.format(args))
   ...: 

In [3]: fun1(1, 2, 3)
Passed arguments: a=1 b=2 c=3

In [4]: fun2(1, 2, 3)
Passed args: (1, 2, 3)

In [5]: fun2([1, 2, 3])
Passed args: ([1, 2, 3],)

In [6]: fun2(*[1, 2, 3])
Passed args: (1, 2, 3)

In [7]: fun1(*[1, 2, 3])
Passed arguments: a=1 b=2 c=3

在第三次调用中,我们分别传递了3个参数,这与调用未打包列表时使用第七次调用的情况相同。将其与调用
fun2
时的情况进行比较。

**kwargs允许您将参数的关键字可变长度传递给函数。如果要处理函数中的命名参数,则应使用**kwargs。下面是一个示例,让您了解这一点:

def greet_me(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.iteritems():
            print "%s == %s" %(key,value)

>>> greet_me(name="yasoob")
name == yasoob

**kwargs允许您将参数的关键字可变长度传递给函数。如果要处理函数中的命名参数,则应使用**kwargs。下面是一个示例,让您了解这一点:

def greet_me(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.iteritems():
            print "%s == %s" %(key,value)

>>> greet_me(name="yasoob")
name == yasoob

我敢打赌,除了
search\u kwargs
之外,某个地方也在向该函数传递一个参数。如果它是回调函数的一部分,那么回调函数很有可能使用一些参数调用它,这些参数被分配给第一个参数
query

我能看到您得到该错误的唯一方法是使用参数kwargs调用函数,如下所示:

假设:

def _mget_search(query, with_scores=False, count=False, record_term=True,
**kwargs): 
那么获取该错误消息的方法是:

>>> search_kwargs= {'query': u'ouuuuu', 'count': False, 'min_score': 20, 'end': 49, 'with_scores': False, 'start': 0, 'max_score': inf, 'record_term': True}
>>> _mget_search(some_random_parameter, **search_kwargs)
下面是我用来尝试重新创建错误的内容

def func(a, b=2, **kwargs):
    return '{}{}{}'.format(a, b, kwargs)
只有最后一个成功地得到了那个错误

>>> func(**{'a':2, 'b': 3, 'other': 3})
"23{'other': 3}"
>>> func(7, **{'stuff': 5})
"72{'stuff': 5}"
>>> func(2, **{'b': 7})
'27{}'
>>> func(**{'b': 3, 'other': 3, 'a': 5})
"53{'other': 3}"
>>> func(2, **{'a': 5})
TypeError: func() got multiple values for argument 'a'

我敢打赌,除了
search\u kwargs
之外,某个地方也在向该函数传递一个参数。如果它是回调函数的一部分,那么回调函数很有可能使用一些参数调用它,这些参数被分配给第一个参数
query

我能看到您得到该错误的唯一方法是使用参数kwargs调用函数,如下所示:

假设:

def _mget_search(query, with_scores=False, count=False, record_term=True,
**kwargs): 
那么获取该错误消息的方法是:

>>> search_kwargs= {'query': u'ouuuuu', 'count': False, 'min_score': 20, 'end': 49, 'with_scores': False, 'start': 0, 'max_score': inf, 'record_term': True}
>>> _mget_search(some_random_parameter, **search_kwargs)
下面是我用来尝试重新创建错误的内容

def func(a, b=2, **kwargs):
    return '{}{}{}'.format(a, b, kwargs)
只有最后一个成功地得到了那个错误

>>> func(**{'a':2, 'b': 3, 'other': 3})
"23{'other': 3}"
>>> func(7, **{'stuff': 5})
"72{'stuff': 5}"
>>> func(2, **{'b': 7})
'27{}'
>>> func(**{'b': 3, 'other': 3, 'a': 5})
"53{'other': 3}"
>>> func(2, **{'a': 5})
TypeError: func() got multiple values for argument 'a'

我认为这是因为
query
被定义为一个位置参数,因此当您与**一起传递的字典被解包时,第一个条目(无论其名称)将用于查询,然后查询也会出现在字典中,因此
query
的多个值

尝试通过将查询设置为命名参数进行修复:

def _mget_search(query='', with_scores=False, count=False, record_term=True, **kwargs):

或者,在传递查询时不要将其包含在字典中。

我认为问题是因为
query
被定义为一个位置参数,因此当使用**传递的字典解包时,第一个条目(无论其名称)将用于查询,然后查询也会出现在字典中,因此,
查询
有多个值

尝试通过将查询设置为命名参数进行修复:

def _mget_search(query='', with_scores=False, count=False, record_term=True, **kwargs):

或者,传递查询时不要将其包含在字典中。

在最后一个代码块中交换第一个示例中的参数顺序时会发生什么:
func(**{b':3,'other':3,'a':2})
?我认为这就是问题所在“a”不再是第一个参数。@JGC nice!错过了。在解释器中测试并通过。编辑答案以反映这一点。在最后一个代码块中交换第一个示例中的参数顺序时会发生什么情况:
func(**{'b':3,'other':3,'a':2})
?我认为这就是问题所在“a”不再是第一个参数。@JGC nice!错过了。在解释器中测试并通过。编辑的答案反映了这一点。