赋值语句左侧与右侧的Star*运算符

Jim*_*ard 11 python iterable python-3.x iterable-unpacking

这个问题源于PEP 448- 其他解包通用化,并且据我所知(并且没有后端移植到2.x),它存在于Python 3.5中.具体而言,在" 缺点 "一节中,注意到以下内容:

虽然*elements, = iterable原因elements是一list, elements = *iterable,导致elements成为一个tuple.造成这种情况的原因可能会让那些不熟悉这种结构的人感到困惑.

确实如此,因为iterable = [1, 2, 3, 4]第一种情况产生了list:

>>> *elements, = iterable
>>> elements
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

而对于第二种情况tuple,创建了一个:

>>> elements = *iterable,
>>> elements
(1, 2, 3, 4)
Run Code Online (Sandbox Code Playgroud)

由于不熟悉这个概念,我很困惑.谁能解释这种行为?已加星标的表达方式是否会根据其所在的方式而有所不同?

Jim*_*ard 13

在考虑扩展拆包的初始PEP时,解释了这两种情况之间的区别:PEP 3132 -- Extended iterable unpacking.

在PEP的摘要中我们可以看到:

此PEP建议更改可迭代解包语法,允许指定"catch-all"名称,该名称将分配未分配给"常规"名称的所有项目的列表.

(强调我的)

所以在第一种情况下,执行后:

*elements, = iterable
Run Code Online (Sandbox Code Playgroud)

elements总是会list包含所有项目iterable.

即使它在两种情况下看起来都相似,但*在这种情况下(左侧)意味着:捕获未分配给名称的所有内容并将其分配给已加星标的表达式.它的工作原理类似的方式作为*args**kwargs在做的函数定义.

def spam(*args, **kwargs): 
    """ args and kwargs group positional and keywords respectively """
Run Code Online (Sandbox Code Playgroud)

第二种情况(右侧)有些不同.在这里,我们没有*工作在"捕捉一切"的方式,就像我们通常在函数调用中一样工作.它扩展了附加到的迭代的内容.所以,声明:

elements = *iterable, 
Run Code Online (Sandbox Code Playgroud)

可以视为:

elements = 1, 2, 3, 4, 
Run Code Online (Sandbox Code Playgroud)

这是tuple初始化的另一种方式.

待办事项,一个list可以通过简单的使用创建elements = [*iterable]将解压的内容iterable[],并导致形式的分配elements = [1, 2, 3, 4].