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

Python *参数在函数定义中的位置,python,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, 1, 2, 3, 1, 3) 我称之为: fu

我定义了这样一个函数:

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, 1, 2, 3, 1, 3)
我称之为:

func(1, op1=1, op2=2, op3=3, 1, 3)
当然,我有一个错误:

在我看来,
*参数是位置参数。而
op1
op2
op2
是关键字参数。因此,
*参数
应该在
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解释器不认为第一个定义是错误的

大家好, 我更新了这个话题

与同事讨论后,我认为:

  • 函数的定义,参数为默认或非默认参数

  • 调用函数时,参数是位置参数或关键字参数


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

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

    Python在调用函数时确定哪个参数是
    关键字

    这里有更多的例子:

    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
    

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

    func(must, op1=1, op2=2, op3=3, *args, **kwargs)
    
    这意味着
    op1
    op2
    op3
    是可选的位置参数。如果不先明确设置所有三个参数,则不能指定任何
    *args
    。出现错误是因为您试图将位置参数放在关键字之后。关键字命名位置参数是不相关的。您可以这样拨打相同的电话:

    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, 1, 2, 3, 1, 3)
    
    这不会引起错误。也不会

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

    除了
    *args
    ,所有位置参数都是命名的,也可以通过关键字传入。但实际上,在作为关键字传入的第一个参数之后的所有参数都必须作为关键字传入。因此,如果将任何命名的位置参数作为关键字传入,则不能传入
    *args

    在第二个示例中,您仅通过将op arguments关键字放在splat(
    *
    )之后来创建它们。因此,第一个参数之后的任何位置参数都会被吸收到
    *args

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


    另一方面,splat参数按惯例命名为
    *args
    ,splattysplatone
    **kwargs
    。在整个回答过程中,我一直坚持这个惯例。

    请将错误以文本形式发布。不要发布控制台输出的图像。我不知道为什么会有人投反对票。你在这里有一个合理的问题,你显然已经试图自己去理解它。请看幻灯片8到30。请在您的答案中添加更多信息。1.为什么op1、op2和op3不是关键字参数。2.为什么seconde代码段可以工作。是的,它可以工作,但是这个调用将所有参数都视为位置参数,这不符合我的期望,例如,我希望调用如下内容:func(1,op2=4,7,a=1,b=2)