是否可以交替使用* args和** kwargs?

时间:2013-11-12 22:01:49

标签: python python-2.7 args kwargs

想象一下,我有一个看起来像这样的函数:

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

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

myFunction(*bigList):

bigList看起来像= [[1,2,3],[4,5,6],'hello',[1,3,5],[2,4,6],'world',etc...]

但是,现在我需要每三个人都有一个kwarg。因此,在我看来,列表“看起来”就像这样:

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

因此,有两个问题要做到这一点。

1)我可以构建一个包含kwarg字符串的列表,而不将函数作为实际参数读入吗? word中的newBigList(s)可以是字符串吗?

2)你可以替换kwargs和args吗?我知道kwargs通常都是用字典做的。是否可以通过交替使用两者?

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

编辑这是方法。它是一个matplotlib方法,绘制一个多边形(或一堆多边形):

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

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

问题是,要使用颜色参数的RBG值,我需要包含颜色关键字。更复杂的是,我使用random.random()模块生成一个随机元组。

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

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它们都是一个元组并且像这样使用它。

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

但是,现在我需要这些关键字。如果需要,我非常乐意提供更多信息。感谢

3 个答案:

答案 0 :(得分:3)

简短回答:不。

更长的答案:取决于你想要做什么。 Python界面不能接受你想要的签名,那么函数是什么,你实际上想要做什么?

答案 1 :(得分:3)

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

  

如果使用一个绘图命令创建多行,则kwargs将应用于所有这些行,例如:

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

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

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

答案 2 :(得分:3)

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

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

      

    如果使用一个plot命令创建多行,则kwargs适用于   所有这些行

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


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

首先,有不同类型的参数。我将举一个例子来解释这些差异:

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

此功能有:

  • 两个参数pos_kw1pos_kw2,可以通过位置参数或关键字参数分配
  • 可以使用位置参数
  • 指定的参数*args
  • 可以使用关键字参数
  • 指定的参数kw_only

注意:默认值与关键字参数有关。他们只是不需要参数。

要理解参数传递的机制,你可以认为(尽管并非严格说来),如果python执行函数调用(例如):

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

它首先将所有位置参数收集到元组中。在上面的情况下,结果元组将是pos_args = (1, 2, 'a', 'b', 'c'),然后将所有关键字参数收集到dict中,在这种情况下为kw_args = {'kw_only': 7},之后,它会调用函数执行:

a_function(*pos_args, **kw_args)

注意:由于dict未订购,因此关键字的顺序无关紧要。

在你的问题中,你想做类似的事情:

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 first 扩展了*pos_args而没有考虑关键字参数,之后它扩展了**kw_args。如果您认为在这个术语中您可以清楚地理解函数调用,例如:

# 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是一个简单的元组解包操作,相当于:

pos_kw1, pos_kw2, *args = pos_args

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

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

由于这些限制,允许在关键字参数之后出现位置的函数调用没有任何意义,因此你不能做类似的事情:

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

允许这样的函数调用只会欺骗人们让他们认为顺序对关键字很重要,或者在解包等时可以跳过参数。因此Python只会引发错误并避免这种歧义。