理解'*'&引用;“仅关键字”;python3函数中的参数表示法

理解'*'&引用;“仅关键字”;python3函数中的参数表示法,python,python-3.x,keyword-argument,Python,Python 3.x,Keyword Argument,我在使用python3时遇到了一些问题。其他仅基于关键字的参数 这是我的密码: 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

我在使用python3时遇到了一些问题。其他仅基于关键字的参数

这是我的密码:

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\u 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
>>>

您得到的错误-
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)==>awesome_函数(3,5,前缀=“$”)

这是一个简单的例子-

>>> 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'

根据的语义,要传递的参数的规则如下

参数列表::=位置参数[“,”关键字参数]
[“,”“*”表达式][“,”关键字\u参数]
[“,”“**”表达式]
|关键字参数[“,”“*”表达式]
[”,“关键字参数][”,“**”表达式]
|“*”表达式[”,“关键字参数][”,“***”表达式]
|“**”表达式
正如您在这里看到的,位置参数应该始终出现在函数调用的开头。它们不能出现在其他任何地方。当你这样做的时候

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


但是,当您使用
partial
时,它会起作用,因为
partial
会创建一个新的函数对象,并存储要传递给它的所有参数。当您实际调用由
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
awesome_function(prefix='$', 3, 5)