【问题标题】:Is it possible to alternate the use of *args and **kwargs?是否可以交替使用 *args 和 **kwargs?
【发布时间】:2013-11-12 22:01:49
【问题描述】:

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

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 构造一个包含字符串的列表吗? newBigList 中的 word(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)

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

【问题讨论】:

  • 我不想想象这样的功能。如果您需要将这么多参数传递给函数,我建议您将其功能拆分为更小的函数
  • 不幸的是,这不是我自己的功能。它来自 matplotlib 库。我只是想更一般地问这个问题,以防人们想知道......
  • 重构你的函数来获取一个类的对象,成员:a=[1,2,3], b=[4,5,6], word='hello'
  • 我不明白这个问题。我很确定您所询问的函数签名在 Python 中是非法的。你能举个例子,一个真实的函数和你想用它来调用它的参数吗?
  • 这不是有效的python:SyntaxError: non-keyword arg after keyword arg。请展示一个最小的工作示例,我们可以运行来演示问题。来自 matplotlib 的文档:“*kwargs 可用于设置线条属性(任何具有 set_* 方法的属性)。[省略] 如果您使用一个绘图命令制作多条线条,*kwargs 适用于所有这些行”。我相信您假设能够为每一行使用一次color=:这是不可能。多次使用相同的关键字是错误的。

标签: python python-2.7 args keyword-argument


【解决方案1】:

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

如果您使用一个绘图命令制作多行,则 kwargs 适用于所有这些行,例如:

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

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

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

【讨论】:

  • 谢谢,我会用十六进制值来表示颜色。好主意,不敢相信我错过了它
【解决方案2】:

简短回答:不。

更长的答案:取决于您要做什么。 Python接口无法接受你想要的签名,那么函数是什么,你到底想做什么?

【讨论】:

    【解决方案3】:

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

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

      如果您使用一个绘图命令制作多行,则 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)
    

    注意:因为dicts 没有排序,所以关键字的顺序无关紧要。

    在您的问题中,您想执行以下操作:

    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。如果你从这个术语中思考你可以清楚地理解一个函数调用如:

    # 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 只会引发错误并避免这种歧义。

    【讨论】:

      猜你喜欢
      • 2020-09-16
      • 2017-01-28
      • 2017-03-26
      • 2021-07-26
      • 2022-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多