在函数调用中传递的参数的Python排序规则

时间:2018-08-19 06:28:51

标签: python

我尝试使用*和**将任意数量的参数传递给函数。在Mark Lutz撰写的“ Learning Python”中,它说首先要遵循位置(值)的顺序,然后是关键字参数(名称=值)和*序列的组合,然后是** dict。但是,我发现位置参数(如果存在)需要首先出现,但是在一定程度上可以将其余三个位置参数按顺序混合使用。
代码keyword3.py:

def     func(a, b=1, *pArgs, **kwArgs): 
        print("a = {0}, b = {1}".format(a,b))
        print("Positional args = {}".format(pArgs))
        print("Keyword args = {}".format(kwArgs))

通过反复试验,

[1]在关键字和** dict之间,它们可以任意顺序...

>>> import keywords3 as j

>>> j.func(b = 3, **{'a':2,'c':4,'d':5})
a = 2, b = 3
Positional args = ()
Keyword args = {'d': 5, 'c': 4}
>>> j.func( **{'a':2}, b = 3, **{'c':4})
a = 2, b = 3
Positional args = ()
Keyword args = {'c': 4}

[2]在位置args和*序列之间,它们可以是任意顺序...

>>> j.func(*(2, 3), 4, *(5, 6))
a = 2, b = 3
Positional args = (4, 5, 6)
Keyword args = {}
>>> j.func(2, *(3, 4), 5, *(6,7), **{'c':8})
a = 2, b = 3
Positional args = (4, 5, 6, 7)
Keyword args = {'c': 8}

[3]通常,在关键字或** dict参数之前,必须出现位置或序列参数。

>>> j.func(*(3, 4), 5, *(6,7), d=15, **{'c':8}, e=16)
a = 3, b = 4
Positional args = (5, 6, 7)
Keyword args = {'e': 16, 'd': 15, 'c': 8}

>>> j.func(d=15, 5, *(6,7), **{'c':8}, e=16)
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument

>>> j.func(**{'a':2}, 5, *(6,7), **{'c':8}, e=16)
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument unpacking

>>> j.func(**{'a':2}, *(6,7), **{'c':8}, e=16)
  File "<stdin>", line 1
SyntaxError: iterable argument unpacking follows keyword argument unpacking

[4]一个例外是关键字参数后面的可迭代参数解压缩*(6,7)没问题...

>>> j.func(f=5, *(6,7), **{'c':8}, e=16)
a = 6, b = 7
Positional args = ()
Keyword args = {'e': 16, 'f': 5, 'c': 8}

这些观察正确吗?请发表评论。

1 个答案:

答案 0 :(得分:3)

有一个单个规则与您的所有示例都一致:位置参数位于命名参数之前。

在所有示例中,***拆包运算符。例如,当您写

f(1, *(2,3), 4)

语言得到

f(1,2,3,4)

它们是所有位置参数,该语言不知道它们之间的区别。对于**运算符也是如此。

但是,当您违反该唯一规则时,例如

j.func(**{'a':2}, 5, *(6,7), **{'c':8}, e=16)

由于出现错误,因为在此示例中,**{'a':2}等效于a=2,后者在位置参数5之前。