*参数在函数定义中的位置

时间:2019-01-23 08:17:13

标签: python

我定义了这样一个函数:

def func(must, op1=1, op2=2, op3=3, *arguments, **keywords):
    print(must, op1, op2, op3)
    for arg in arguments:
        print(arg)
    for kw in keywords.keys():
        print(kw, ":", keywords[kw])

我叫它:

func(1, op1=1, op2=2, op3=3, 1, 3)

当然,我得到了一个错误:

Error information

在我看来,*arguments是位置参数。 op1op2op2是关键字参数。因此,*arguments应该在op1op2op3之前。然后我更改了定义:

def func(must, *arguments, op1=1, op2=2, op3=3, **keywords):
    print(must, op1, op2, op3)
    for arg in arguments:
        print (arg)
    for kw in keywords.keys():
        print (kw, ":", keywords[kw])

为什么Python解释器不认为第一个定义是错误的?

大家好, 我更新了这个主题。

与同事讨论后,我认为:

  1. 函数定义,参数为默认参数或非默认参数

  2. 调用功能,参数为位置参数或关键字参数

因此,参数是否为位置参数取决于您调用函数,而不是定义函数。

2 个答案:

答案 0 :(得分:0)

虽然有点违反直觉,但第一个定义是完全明确的:

func(must, op1=1, op2=2, op3=3, *args, **kwargs)

这意味着op1op2op3是可选的位置参数。如果未先明确设置所有三个,则不能指定*args中的任何一个。您收到错误消息是因为您尝试将位置参数放在关键字之后。关键字命名位置参数无关紧要。您可以像这样拨打相同的电话:

func(1, 1, 2, 3, 1, 3)

这不会引发错误。都不会

func(1, 2)

在这种情况下,只有op1将具有非默认值,*args将为空,并且您可以设置所需的任何关键字,包括op2和{{1} }。

op3外,所有位置参数均已命名,并且也可以通过关键字传递。不过,实际上,所有在第一个参数之后作为关键字 传递的参数都必须作为关键字传递。因此,如果您将任何命名的位置参数作为关键字传递,则无法传递*args

在第二个示例中,您将op参数设置为仅关键字,方法是将其放在splat(*args)之后。因此,第一个之后的所有位置参数都将吸收到*中。

请记住,仅关键字参数不需要默认值。像*args这样的函数只能 作为def func(*, a): pass调用,而永远不能作为func(a=3)调用。

在旁注中,splat自变量通常命名为func(3),splatty splat自变量*args。在整个回答过程中,我始终坚持这一约定。

答案 1 :(得分:-1)

在第一个示例中,您可以像这样调用函数(它仍在工作):

func(9, 9, 9, 9)

Python在调用函数时确定哪个参数是keyword

更多示例:

def func(a,b,c=1,d): # -> a, b, c, d are parameters and c has default value = 1
     pass

func(1, 2, 3, 4) # -> call with 4 postional parameters

func(1, 3, d=3) # -> call with 2 positional parameters and 1 keyword parameters