理解 Python 交换:为什么 a, b = b, a 并不总是等同于 b, a = a, b?

新手上路,请多包涵

众所周知,交换两个项目 ab 的值的pythonic方法是

a, b = b, a

它应该等同于

b, a = a, b

然而,今天在写一些代码的时候,无意中发现下面两个swap给出了不同的结果:

 nums = [1, 2, 4, 3]
i = 2
nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]
print(nums)
# [1, 2, 4, 3]

nums = [1, 2, 4, 3]
i = 2
nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]
print(nums)
# [1, 2, 3, 4]

这让我难以置信。有人可以向我解释这里发生了什么吗?我认为在 Python 交换中,两个分配同时且独立发生。

原文由 Shaun Han 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 942
2 个回答

来自 python.org

将对象分配给目标列表(可选地括在圆括号或方括号中)递归定义如下。

  • Else:该对象必须是一个可迭代对象,其项目数与目标列表中的目标数相同,并且项目从左到右分配给相应的目标。

所以我将其解释为您的作业

nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]

大致相当于

tmp = nums[nums[i]-1], nums[i]
nums[i] = tmp[0]
nums[nums[i] - 1] = tmp[1]

(当然有更好的错误检查)

而另一个

nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]

就好像

tmp = nums[i], nums[nums[i]-1]
nums[nums[i] - 1] = tmp[0]
nums[i] = tmp[1]

因此,在这两种情况下,首先评估右侧。但是然后左边的两块按顺序求值,求值后马上做作业。至关重要的是,这意味着左侧的第二项仅 第一项分配完成后才进行评估。因此,如果您首先更新 nums[i] ,那么 nums[nums[i] - 1] 指的是与更新 nums[i] 不同的索引。

原文由 Silvio Mayolo 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是因为评估——特别是在 = 的 _左侧_——从左到右发生:

 nums[i], nums[nums[i]-1] =

首先 nums[i] 被分配,然后 值用于确定分配给 nums[nums[i]-1] 的索引

像这样做作业时:

 nums[nums[i]-1], nums[i] =

nums[nums[i]-1] nums[i] 旧值,因为分配给 nums[i] 仍然在后面

原文由 trincot 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题