关于python:是否可以交替使用*args和**kwargs?

Is it possible to alternate the use of *args and **kwargs?

假设我有这样一个函数:

1
myFunction(arg, arg, kwarg, arg, arg, kwarg, etc...):

其中arg是arg,而kwarg是kwarg。在此之前,我的函数看起来像myFunction(*args):,我只使用了一长串*参数,我将传入这样的大列表

1
myFunction(*bigList):

大名单看起来是=[[1,2,3],[4,5,6],'hello',[1,3,5],[2,4,6],'world',etc...]

但是,现在我需要每三次就有一次夸格的辩论。所以,在我看来,这个列表现在看起来是这样的:

1
newBigList = [[1,2,3],[4,5,6],word='hello',[1,3,5],[2,4,6],word='world',etc...]

所以,有两个问题可以解决这个问题。

1)我可以为Kwarg构造一个带有字符串的列表,而不需要函数将其作为实际参数读取?newBigList中的word可以是字符串吗?

2)您能交替使用Kwarg和ARG吗?我知道夸克语通常是用字典来完成的。是否可以交替使用两者?

像往常一样,如果有人知道更好的方法,我会很乐意改变我的方式。

编辑方法如下。它是一种绘制多边形(或一组多边形)的matplotlib方法:

1
plot([x1], [y1], color=(RBG tuple), [x2], [y2], color=(RGB tuple), etc...)

其中,[x1]是第一个多边形的x值列表,[y1]是第一个多边形的y值列表,依此类推。

问题是,要使用rbg值作为color参数,我需要包含color关键字。为了使事情更加复杂,我使用random.random()模块生成了一个随机元组。

所以,我有所有多边形的x值列表,所有多边形的y值列表,以及随机RBG颜色的元组列表。它们看起来像这样:

1
2
3
x = [[1,2,3], [4,5,6], [7,8,9]]
y = [[0,9,8], [7,6,5], [4,3,2]]
colors = [(.45, .645, .875), (.456, .651, .194), (.813, .712, .989)]

所以,有三个多边形要绘制。在我能做关键字之前,我一直在做的是zip,所有这些关键字组合成一个元组,然后像这样使用。

1
2
3
list_of_tuples = zip(x, y, colors)
denormalized = [x for tup in list_of_tuples for x in tup]
plot.plot(*denormalized)

但是,现在我需要那些关键词。如果需要的话,我很乐意提供更多的信息。谢谢


有几个原因阻止你做你想做的事情:

  • 在函数调用中只能指定一次关键字,因此color=something, ..., color=other引发异常
  • 不能混合关键字参数和位置,因此x1, y1, color=something, x2是一个错误。
  • 即使按您的预期工作,仍然有matplotlib的文档说明:


    If you make multiple lines with one plot command, the kwargs apply to
    all those lines

    也就是说,您不能只对其中一条线路使用color=,或对每条线路使用一次。这是一个"全球性"的财产。如果要为每一行指定不同的颜色,则必须使用其他提供线条颜色的方法。

我相信,通过您的问题,您不清楚位置和关键字参数是如何工作的,所以我将尝试在这方面给您一个线索。

首先,有不同类型的参数。我将介绍一个例子来解释这些区别:

1
def a_function(pos_kw1, pos_kw2, *args, kw_only)

此功能具有:

  • 两个参数pos_kw1pos_kw2都可以通过位置参数或关键字参数来分配。
  • 只能用位置参数指定的参数*args
  • 参数kw_only只能用关键字参数指定。

注意:默认值与关键字参数无关。它们只是使参数不需要。

要理解参数传递的机制,您可以认为(尽管它不是严格正确的),如果在Python执行函数调用(例如)时:

1
a_function(1, 2, *'abc', kw_only=7)

它首先将所有位置参数收集到一个元组中。在上述情况下,生成的元组将是pos_args = (1, 2, 'a', 'b', 'c'),然后将所有关键字参数收集到dict中,在这种情况下,kw_args = {'kw_only': 7}中,然后调用函数doing:

1
a_function(*pos_args, **kw_args)

注:由于dicts没有排序,关键字的顺序无关紧要。

在你的问题中,你想做如下的事情:

1
plot(x, y, color=X, x2, y2, color=Y, ...)

由于调用实际使用的是*pos_args**kw_args函数:

  • 不知道color=X是在y之后指定的。
  • 不知道color=Y是在y2之后指定的。
  • 不知道color=X是在color=Y之前指定的。

推论:不能多次指定同一个参数,因为Python无法知道应该将哪个匹配项分配给哪个参数。同样,在定义函数时,不能使用两个同名参数。(不,python不会自动构建值列表或类似的列表。它只会引发一个错误。)

您也可以认为python首先扩展*pos_args,而不考虑关键字参数,然后扩展**kw_args。如果您这样认为,您可以清楚地理解函数调用,例如:

1
2
3
4
5
6
7
# naive intent: assign pos_kw1 via keyword and pos_kw2 via positional
# assuming python will skip positional that were already provided as keyword args

a_function(1, pos_kw1=2)

# or even:
a_function(pos_kw1=2, 1)   # hoping order matters

没有任何意义,因为1通过位置参数分配给pos_kw1,并且在扩展关键字参数时,它将被重新分配。

另一种解释是,在调用a_function(*pos_args, **kw_args)时,*pos_args是一个简单的tuple解包操作,相当于:

1
pos_kw1, pos_kw2, *args = pos_args

(在python2中,不能使用*,但这是*args参数或多或少工作的方式)。

tuple解包不会跳过元素:它只分配给tuple的连续元素,函数调用也一样:不检查位置参数是否已经通过关键字传递,最终是否被跳过。他们只是被盲目地分配。

由于这些限制,允许位置出现在关键字参数之后的函数调用没有任何意义,因此不能执行以下操作:

1
plot(x, y, color=X, x2, ...)

允许这样的函数调用只会欺骗人们,让他们认为关键字的顺序很重要,或者在解包等操作时可以跳过参数,所以python只会引发一个错误,并避免这种模糊性。


函数签名不能像您认为的那样工作。matplotlib的plot函数的关键字参数适用于您指定的所有行:

If you make multiple lines with one plot command, the kwargs apply to all those lines, e.g.:

1
plot(x1, y1, x2, y2, antialised=False)

如果要为每行指定单独的颜色,则需要将它们转换为格式字符串,可以作为每三个位置参数传递。也许您可以将它们格式化为HTML样式的十六进制代码:#RRGGBB

或者,每行调用一次plot,将color元组作为关键字参数传递一次。


简短回答:不。

更长的答案:取决于你到底想做什么。python接口不能接受您想要的签名,那么函数是什么,您实际上想做什么?