我定义了这样一个函数:
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)
当然,我得到了一个错误:
在我看来,*arguments
是位置参数。 op1
,op2
,op2
是关键字参数。因此,*arguments
应该在op1
,op2
,op3
之前。然后我更改了定义:
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解释器不认为第一个定义是错误的?
大家好, 我更新了这个主题。
与同事讨论后,我认为:
函数定义,参数为默认参数或非默认参数
调用功能,参数为位置参数或关键字参数
因此,参数是否为位置参数取决于您调用函数,而不是定义函数。
答案 0 :(得分:0)
虽然有点违反直觉,但第一个定义是完全明确的:
func(must, op1=1, op2=2, op3=3, *args, **kwargs)
这意味着op1
,op2
和op3
是可选的位置参数。如果未先明确设置所有三个,则不能指定*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