Python中的同时赋值语义

Posted

技术标签:

【中文标题】Python中的同时赋值语义【英文标题】:Simultaneous assignment semantics in Python 【发布时间】:2013-04-30 20:48:23 【问题描述】:

考虑以下 Python 3 代码:

a = [-1,-1,-1]
i = 0

现在考虑以下两个版本的同时分配 a 和 i:

作业版本 1:

a[i],i = i,i+1

作业版本 2:

i,a[i] = i+1,i

我希望这两个版本的同时分配在语义上是等效的。但是,如果您在每次同时分配后检查 a 和 i 的值,您会得到不同的状态:

分配版本 1 后 print(a,i) 的输出:

[0, -1, -1] 1

分配版本 2 后 print(a,i) 的输出:

[-1, 0, -1] 1

我不是 Python 语义方面的专家,但这种行为看起来很奇怪。我希望这两个分配都表现为分配版本 1。此外,如果您检查以下链接,人们会希望两个分配版本都导致相同的状态:

Link to book excerpt in Google Books

关于同时分配的 Python 语义,我是否遗漏了什么?

注意:这种奇怪的行为似乎无法重现,例如,当变量a 具有整数类型时;它似乎要求a 是列表类型(也许任何可变类型都是这种情况?)。

【问题讨论】:

【参考方案1】:

在这种情况下:

i, a[i] = i + 1, i

右侧计算为元组 (1, 0)。然后这个元组被解压到i,然后是a[i]a[i]解包期间被评估,而不是之前,因此对应于a[1]

由于在进行任何解包之前评估右侧,因此无论 i 的最终值如何,在右侧引用 a[i] 将始终为 a[0]

这是另一个无用的有趣示例供您锻炼

>>> a = [0,0,0,0]
>>> i, a[i], i, a[i] = range(4)
>>> a
[1, 0, 3, 0]

【讨论】:

谢谢gnibbler,我看到了你提出的关于元组评估的技术要点;从这个角度来看,一切都说得通。但是,从语义的角度来看,我仍然不知所措,因为那时 simultaneous 分配语义不是非常同时的。由于我是 Python 新手,我会抓住机会询问是否有官方文档,其中包含 Python 赋值语义的正式/半正式定义。你知道有这样的文件吗? @hquilo:“同时分配”甚至没有出现在 Python 文档中。 a, b = 1, 2 只是(a, b) = (1, 2) 的简写,称为序列解包。 谢谢@gnibler 和@Blender;你的回答让事情变得清晰。 只是为了添加对文档的引用(docs.python.org/3/reference/simple_stmts.html):“虽然赋值的定义意味着左侧和右侧之间的重叠是'同时'的(例如a, b = b, a 交换两个变量),重叠分配给变量的集合从左到右发生,有时会导致混淆。”

以上是关于Python中的同时赋值语义的主要内容,如果未能解决你的问题,请参考以下文章

python变量存储,理解赋值浅拷贝深拷贝

使用 Python 语义对 R 中的嵌套列表进行排序

Python3基本数据类型

python——赋值与深浅拷贝

python中的变量

Python3 基本数据类型