Python - 方法参数中的值解包顺序

8
def fun(a, b, c, d):
    print('a:', a, 'b:', b, 'c:', c, 'd:', d)

为什么这个有效

fun(3, 7, d=10, *(23,))

并且打印出:
a: 3 b: 7 c: 23 d: 10

当这件事发生时

fun(3, 7, c=10, *(23,))

不会

Traceback (most recent call last):
  File "/home/lookash/PycharmProjects/PythonLearning/learning.py", line 10, in <module>
    fun(3, 7, c=10, *(23,))
TypeError: fun() got multiple values for argument 'c'

我不知道错误被抛出的确切原因,但你在关键字参数后面永远不应该有可变参数。通常会抛出一个错误,但元组解包似乎会抛出一个与正常“语法错误:位置参数跟随关键字参数”不同的错误。 - Error - Syntactical Remorse
@错误-语法忏悔。我认为你没有理解重点。原帖作者已经发现了一种情况,即在关键词之后实际上可以放置一个位置,它确实可以工作。 - Mad Physicist
@MadPhysicist 我了解您的意思。但我更倾向于只是陈述元组解包不应该在关键字参数之后进行。因此,我将其作为评论而不是答案。 - Error - Syntactical Remorse
1
很棒的问题。我从来不知道这件事。 - Error - Syntactical Remorse
1个回答

6
通过使用*(23,),您正在将元组(23,)中的值作为位置参数进行解包,跟随已经定义的位置参数,即a3b7。因此,23将被分配给参数c,这就是为什么fun(3, 7, d=10, *(23,))有效,但在fun(3, 7, c=10, *(23,))中,您还将值10分配给关键字参数c,因此会发生冲突,因为c不能同时赋值为2310
请注意,虽然合法,但有些人不建议在关键字参数之后解包可迭代参数,如此处所讨论的,尽管最终该语法被认定为保留。

很明显发生了什么,但是从何时开始你可以在关键字之后解包位置参数? - Mad Physicist
自Python 3以来 - blhsing
你有这方面的来源吗?这是故意的并且有文档支持,还是可以说是一个错误/遗漏? - Mad Physicist
1
@MadPhysicist 我错了,我想到了其他的事情。这个语法在Python 2中也是合法的。正如从CPython测试用例f(1,2,c=3,*d,**e)test_ast.py中可以看出的那样,主要用途是允许包装函数以更直观的方式将可变参数和关键字参数传递给包装函数,通过将可变参数和可变关键字参数放在参数列表的末尾。 - blhsing
@blhsing。是的,我看了那个错误报告,GvR说这不是一个bug。很高兴知道了Python的另一种奥秘。既然很明显这个问题不会很快消失,我迫不及待地想开始不合适地使用它 :) - Mad Physicist
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接