2つは同じだと思います。
nums = [1, 2, 0]
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
print nums # [2, 1, 0]
nums = [1, 2, 0]
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]
print nums # [2, 2, 1]
しかし、結果は異なります。
結果が異なるのはなぜですか? (なぜ2番目の結果になるのですか?)
リストは変更可能です
リストの主要な部分は、リストが変更可能であるということです。これは、リストの値を変更できることを意味します。これがあなたが問題に直面している理由の一つです。 詳細についてはドキュメントを参照してください
評価の順序
もう1つは、タプルを解凍するときに、評価が左から右に開始されることです。 詳細についてはドキュメントを参照してください
a,b = c,d
を実行すると、c
とd
の値が最初に保存されます。次に、左側から始めて、a
の値を最初にc
に変更し、次にb
の値をd
に変更します。
ここでの落とし穴は、b
の値を変更しているときにa
の場所に副作用がある場合、d
が後でb
、これはb
の副作用の影響を受けるa
です。
今あなたの問題に来ています
最初のケースでは、
nums = [1, 2, 0]
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
nums[0]
は最初は1
であり、nums[nums[0]]
は2
と評価されるため、nums[1]
です。したがって、1,2はメモリに保存されます。
タプルの解凍は左側から行われるようになりました。
nums[nums[0]] = nums[1] = 1 # NO side Effect.
nums[0] = 2
したがって、print nums
は[2, 1, 0]
を出力します
ただし、この場合
nums = [1, 2, 0]
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]
nums[nums[0]], nums[0]
は、最初の場合と同じように、2,1をスタックに置きます。
ただし、左側、つまりnums[0], nums[nums[0]]
では、nums[0]
の変更は、nums[nums[0]]
のインデックスとして使用されるため、副作用があります。したがって、
nums[0] = 2
nums[nums[0]] = nums[2] = 1 # NOTE THAT nums[0] HAS CHANGED
nums[1]
は値2
で変更されません。したがって、print nums
は[2, 2, 1]
を出力します
プロセスを追跡するクラスを定義できます。
class MyList(list):
def __getitem__(self, key):
print('get ' + str(key))
return super(MyList, self).__getitem__(key)
def __setitem__(self, key, value):
print('set ' + str(key) + ', ' + str(value))
return super(MyList, self).__setitem__(key, value)
最初の方法の場合:
nums = MyList([1, 2, 0])
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
出力は次のとおりです。
get 0
get 0
get 1
get 0
set 1, 1
set 0, 2
2番目の方法:
nums = MyList([1, 2, 0])
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]
出力は次のとおりです。
get 0
get 1
get 0
set 0, 2
get 0
set 2, 1
どちらの方法でも、最初の3行はタプルの生成に関連し、最後の3行は割り当てに関連しています。最初のメソッドの右側のタプルは(1, 2)
で、2番目のメソッドは(2, 1)
です。
割り当て段階では、最初のメソッドはnums[0]
である1
を取得し、nums[1] = 1
を設定し、次にnums[0] = 2
を設定し、2番目のメソッドはnums[0] = 2
を割り当て、次にnums[0]
である2
を取得し、最後にnums[2] = 1
を設定します。
そのため、python割り当ての優先度は左から右になります。したがって、次のコードでは次のようになります。
nums = [1, 2, 0]
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
最初にnums[0]
をnums[nums[0]]
に割り当てました。これはnums[1]==1
を意味し、リストは可変オブジェクトであるため、数値は次のようになります。
[1,1,0]
次に、nums[nums[0]]
がnums[0]
に割り当てられます。これは、nums[0]==2
と:を意味します。
nums = [2,1,0]
そして第二部もそうです。
ここで重要な点は、リストオブジェクトは変更可能であり、コードのセグメントで変更すると、その場で変更できることに注意してください。したがって、残りのコードに影響します。
Pythonは式を左から右に評価します。割り当てを評価するとき、右側が左側の前に評価されることに注意してください。
最初の例では、予想どおり、nums [1]が1に設定され、次にnums [0]が2に設定されます。
2番目の例では、nums [0]が2に設定され、次にnums [2]が1に設定されます。これは、この場合、左側のnums [nums [0] ]は、割り当てが発生したときに実際にnums [2]を参照しています。これは、nums [0]が2に設定されたばかりだからです。