【问题标题】:understanding '*' "keyword only" argument notation in python3 functions [duplicate]理解python3函数中的“*”“仅限关键字”参数表示法[重复]
【发布时间】:2016-01-13 07:35:49
【问题描述】:

与partial 一起使用时,我在python3 中遇到了keyword only arguments 功能的一些困难行为。其他 info 仅针对关键字参数。

这是我的代码:

def awesome_function(a = 0, b = 0, *, prefix):
    print('a ->', a)
    print('b ->', b)
    print('prefix ->', prefix)
    return prefix + str(a+b)

以下是我对部分的理解:

>>> two_pow = partial(pow, 2)
>>> two_pow(5)
32
>>>

我的理解是在上面的例子中,partial 将pow 函数的第二个参数作为two_pow 的唯一参数。

我的问题是为什么以下工作:

>>> g = partial(awesome_function, prefix='$')
>>> g(3, 5)
a -> 3
b -> 5
prefix -> $
'$8'
>>>

但我在这方面遇到了错误:

>>> awesome_function(prefix='$', 3, 5)
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>>

我知道我可以直接拨打awesome_function

>>> awesome_function(prefix='$', a = 3, b = 5)
a -> 3
b -> 5
prefix -> $
'$8'
>>>

【问题讨论】:

    标签: python python-3.x keyword-argument


    【解决方案1】:

    根据function calls in Python的语义,传递参数的规则如下

    argument_list   ::=  positional_arguments ["," keyword_arguments]
                           ["," "*" expression] ["," keyword_arguments]
                           ["," "**" expression]
                         | keyword_arguments ["," "*" expression]
                           ["," keyword_arguments] ["," "**"     expression]
                         | "*" expression ["," keyword_arguments] ["," "**" expression]
                         | "**" expression
    

    正如您在此处看到的,位置参数应始终出现在函数调用的开头。它们不能出现在其他任何地方。当你这样做时

    awesome_function(prefix='$', 3, 5)
    

    它违反了上述规则,因为您在关键字参数 (prefix) 之后传递了两个位置参数 (3 和 5)。这就是为什么您会收到 SyntaxError,因为 Python 无法解析函数调用表达式。


    但是,当您使用partial 时,它可以工作,因为partial 创建了一个新的函数对象并存储了所有要传递给它的参数。当您实际调用partial 返回的函数对象时,它首先应用所有位置参数,然后应用关键字参数。

    【讨论】:

      【解决方案2】:

      您得到的错误 - SyntaxError: non-keyword arg after keyword arg - 是因为您尝试在关键字参数之后发送位置参数(如 3,5),这不是有效的语法,因此是语法错误。在函数调用中 -

       awesome_function(prefix='$', 3, 5)
                                ^   ^  ^
                                |     These two are the positional argument.
                                ----- This is the keyword argument.                                
      

      它在使用functools.partial 时有效,因为functools.partial 知道将位置参数放在关键字参数之前,因此当您使用位置参数调用偏函数-g() 时,它会在关键字参数之前发送这些位置参数。因此,在您的情况下 g(3, 5) ==&gt; awesome_function(3, 5, prefix='$') 。

      一个简单的例子来说明这一点 -

      >>> from functools import partial
      >>> def func(a=0,b=1):
      ...     print(a,b)
      ...
      >>> ptfunc = partial(func,a=10)
      >>> ptfunc(20)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: func() got multiple values for argument 'a'
      

      在上面的例子中,当我们调用ptfunc(20)时,20首先作为位置参数传递,然后关键字参数a=10被传递,因此它抱怨它得到了参数a的多个值.


      也如the documentation -中给出的那样

      functools.partial 大致相当于:

      def partial(func, *args, **keywords):
          def newfunc(*fargs, **fkeywords):
              newkeywords = keywords.copy()
              newkeywords.update(fkeywords)
              return func(*(args + fargs), **newkeywords)
          newfunc.func = func
          newfunc.args = args
          newfunc.keywords = keywords
          return newfunc
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-12
        • 2021-11-15
        • 2017-11-26
        • 2014-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多