赋值语句左侧和右侧的星 * 运算符
Posted
技术标签:
【中文标题】赋值语句左侧和右侧的星 * 运算符【英文标题】:Star * operator on left vs right side of an assignment statement 【发布时间】:2016-06-08 18:53:31 【问题描述】:这个问题源于PEP 448
-- Additional Unpacking Generalizations,据我所知,它存在于 Python 3.5 中(而不是向后移植到2.x
)。具体而言,在缺点部分中,指出了以下内容:
虽然
*elements, = iterable
导致elements
成为list
,elements = *iterable
,导致elements
成为tuple
。其原因可能会使不熟悉该构造的人感到困惑。
确实成立,对于iterable = [1, 2, 3, 4]
,第一种情况产生list
:
>>> *elements, = iterable
>>> elements
[1, 2, 3, 4]
而对于第二种情况,tuple
被创建:
>>> elements = *iterable,
>>> elements
(1, 2, 3, 4)
不熟悉这个概念,我很困惑。谁能解释这种行为?加星号的表情是否会根据其所在的一侧而有所不同?
【问题讨论】:
【参考方案1】:在考虑扩展解包的初始 PEP 时解释了这两种情况之间的区别:PEP 3132 -- Extended iterable unpacking
。
在该 PEP 的摘要中,我们可以看到:
此 PEP 提议对可迭代解包语法进行更改,允许指定一个“包罗万象”的名称,将分配一个列表,其中包含未分配给“常规”名称。
(强调我的)
所以在第一种情况,执行后:
*elements, = iterable
elements
始终是一个list
,包含iterable
中的所有项目。
尽管在这两种情况下看起来相似,*
在这种情况下(左侧)意味着:捕获所有未分配给名称的内容并将其分配给加星号的表达式。它的工作方式与*args
和**kwargs
在函数定义 中的工作方式相似。
def spam(*args, **kwargs):
""" args and kwargs group positional and keywords respectively """
第二种情况(右侧)有些不同。在这里,*
不像我们在 函数调用 中通常那样以“捕获一切”的方式工作。它扩展了它所附加的可迭代对象的内容。所以,声明:
elements = *iterable,
可以看成:
elements = 1, 2, 3, 4,
这是初始化tuple
的另一种方式。
请注意,list
可以通过简单地使用 elements = [*iterable]
来创建,这将在 []
中解压缩 iterable
的内容,并生成 elements = [1, 2, 3, 4]
形式的赋值。
【讨论】:
以上是关于赋值语句左侧和右侧的星 * 运算符的主要内容,如果未能解决你的问题,请参考以下文章