为什么*在赋值语句和函数调用中的工作方式不同?

inq*_*One 9 python python-3.x

在Python中,varargs集合的工作方式似乎与赋值语句中的序列拆包方式完全不同。我试图了解这种可能造成混淆的差异的原因。我敢肯定有充分的理由,但这是什么?


# Example 1 with assignment statement
a, *b, c = 1,2,3,4
print(b) # [2, 3]

# Example 1 with function call
def foo(a, *b, c):
    print(b)
foo(1,2,3,4)
Run Code Online (Sandbox Code Playgroud)

该函数调用导致以下错误:

Traceback (most recent call last):
  File "<pyshell#309>", line 1, in <module>
    foo(1,2,3,4)
TypeError: foo() missing 1 required keyword-only argument: 'c'
Run Code Online (Sandbox Code Playgroud)

问题1:为什么不像在赋值语句中那样分配b?

Traceback (most recent call last):
  File "<pyshell#309>", line 1, in <module>
    foo(1,2,3,4)
TypeError: foo() missing 1 required keyword-only argument: 'c'
Run Code Online (Sandbox Code Playgroud)

问题2:为什么类型不同(列表与元组)?

Ism*_*lla 5

在作业中使用时,Python会尝试使其*b匹配以使其有效以使其工作(这是Python 3中的新增功能,请参阅PEP 3132)。这些都是有效的:

a, *b, c = 1,4
print(b) # []

a, *b, c = 1,2,3,4,5 
print(b) # [2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

在函数中使用时,如果*b是函数定义中的第二个参数,则它将与函数调用中倒数第二个参数匹配(如果有)。当您希望函数接受可变数量的参数时使用。一些例子:

def foo(a, *b):
    print(b)
foo(1) # ()
foo(1,2,3,4,5) # (2,3,4,5)
Run Code Online (Sandbox Code Playgroud)

我建议您阅读以下内容:


在列表和元组之间的区别上,最大的是可变性。列表是可变的,元组不是。这意味着这有效:

myList = [1, 2, 3]
myList[1] = 4
print(myList) # [1, 4, 3]
Run Code Online (Sandbox Code Playgroud)

而且这不是:

myTuple = (1, 2, 3)
myTuple[1] = 4 # TypeError: 'tuple' object does not support item assignment
Run Code Online (Sandbox Code Playgroud)

b在这种情况下是列表的原因:

a, *b, c = 1,2,3,4,5 
print(b) # [2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

不是元组(*args在函数中使用时就是这种情况),是因为您可能希望b在赋值后执行某些操作,因此最好将其设为列表,因为列表是可变的。使之成为元组而不是列表是在被接受为功能之前考虑的可能更改之一,如PEP 3132中所述

将加星标的目标设为元组而不是列表。这与函数的* args一致,但使结果的进一步处理变得更加困难。