50

二人は同じだと思います。

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番目の結果になるのですか?)

4

4 に答える 4

51

前提条件- 2 つの重要なポイント


序章

a,b = c,dとの値を実行するcd、最初に保存されます。次に、左辺から順に の値を にa変更しc、次に の値をbに変更しdます。

ここでの問題はb、 の値を変更しているときに の場所に何らかの副作用がある場合、 の副作用の影響を受けるのadが割り当てられることです。 bba


使用事例

今あなたの問題に来ています

最初のケースでは、

nums = [1, 2, 0]    
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]    

nums[0]は最初は1nums[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]value のまま変更されません2。したがって、print nums印刷されます[2, 2, 1]

于 2015-12-09T05:39:37.023 に答える
21

プロセスを追跡するクラスを定義できます。

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)です。

割り当て段階では、最初のメソッド get nums[0]which is1と set nums[1] = 1、次にnums[0] = 22 番目のメソッド assign nums[0] = 2、次に get nums[0]which is 2、最後に setnums[2] = 1です。

于 2015-12-09T05:58:06.797 に答える
11

これは、python 割り当ての優先順位が左から右にあるためです。次のコードでは、次のようになります。

 nums = [1, 2, 0]
 nums[nums[0]], nums[0] = nums[0], nums[nums[0]]

nums[0]最初にto をnums[nums[0]]意味に割り当て、nums[1]==1次にリストは変更可能なオブジェクトであるため、数値は次のようになります。

[1,1,0]

そして、どの手段nums[nums[0]]に割り当てられますおよび :nums[0]nums[0]==2

nums = [2,1,0]

そして、第2部も同様です。

ここで重要な点は、リスト オブジェクトは変更可能であり、コードのセグメントで変更すると、その場で変更できることに注意してください。したがって、残りのコードに影響します。

評価順

Python は式を左から右に評価します。代入を評価する際、右側が左側より先に評価されることに注意してください。

于 2015-12-09T05:43:21.380 に答える
4

最初の例では、ご想像のとおり、nums[1] が 1 に設定され、次に nums[0] が 2 に設定されます。

2 番目の例では、nums[0] が 2 に設定され、次にnums[2]が 1 に設定されます。これは、この場合、左側の nums[nums[0]] が実際に nums[2 を参照しているためです。 ] nums[0] が 2 に設定されたため、割り当てが発生したとき。

于 2015-12-09T05:45:32.507 に答える