1. ホーム
  2. python

[解決済み] Pythonのスワッピングを理解する:なぜa, b = b, aとb, a = a, bは必ずしも等価ではないのですか?

2022-04-23 13:19:28

質問

ご存知のように、2つのアイテムの値を交換するpythonicな方法は ab

a, b = b, a

と同等であるべきです。

b, a = a, b

ところが今日、あるコードを書いていたら、偶然にも以下の2つの入れ替えで異なる結果になることを発見しました。

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のスワップでは、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]

つまり、どちらも右辺が先に評価されるわけです。しかし、その後、左辺の2個が順に評価され、評価後すぐに代入が行われます。決定的なのは、これは、左辺の第2項が評価されるのは、最初の代入が すでに されます。ですから、もしあなたが nums[i] を先に指定すると、その後に nums[nums[i] - 1] を更新した場合とは異なるインデックスを参照します。 nums[i] 2番目。