1

このコードが意図したとおりに動作しない理由を理解するのにしばらく時間を費やすまで、私は常にx += 1構文上の省略形 (およびまったく同等)だと思っていました。x = x + 1

[ipython/euler 72 ]$ def func(mylist):
    mylist += random.sample(range(100),2)
    # do stuff with the random result, then restore original list
    mylist = mylist[:-2]

取得したのと同じリストを返すはずですが、そのようには機能しないようです:

[ipython/euler 81 ]$ x = [1,2,3]

[ipython/euler 82 ]$ func(x)
[1, 2, 3, 23, 7]

[ipython/euler 83 ]$ func(x)
[1, 2, 3, 23, 7, 42, 36]

[ipython/euler 84 ]$ func(x)
[1, 2, 3, 23, 7, 42, 36, 0, 5]

割り当てステートメントを長い形式に変更するmylist = mylist + ...と、期待どおりに機能し、リストは変更されません。

なぜこうなった?リストのオーバーロードされたメソッドとして呼び出されたときにリストが変更可能であり、おそらく iadd が「実際の」追加ではないことに関係していると思いますが、それでもインタープリターがそれらを同等と見なすことを期待していました。

4

2 に答える 2

4

この線

mylist += random.sample(range(100),2)

リストをその場で変更します (そのため、in-place addmylistと呼ばれます)。iaddこれは、呼び出し元のスコープ内の元のリストを変更することを意味します。

mylist = mylist[:-2]

新しいローカル オブジェクトmylistを作成し、それにグローバルの内容を割り当てmylist[:-2]ます。この新しいローカル オブジェクトは、関数から戻るとすぐに破棄されます。

于 2013-09-19T10:23:03.827 に答える
4

お気づきのように、最初のコード ( mylist += random.sample(range(100),2)) はリストをその場で変更します。

これらの両方:

mylist = mylist + ...
mylist = mylist[:-2]

という名前の新しいオブジェクトを作成しますmylist。これには、前の と同じ値 (または派生した値) が与えられmylistます。

このため、後者の行は元のリストを復元しません。新しいコピーを作成し、元の参照をそのままにしておきます。

リストを所定の位置に変更することで、目的の動作を得ることができます。

mylist[:] = mylist[:-2]
于 2013-09-19T10:23:06.880 に答える