2016-10-21 9 views
1

私はpythonパズルを見つけましたが、なぜそれが動作するかを知ることができません。反復中にリストを変更する

x = ['a','b','c'] 
for m in x: 
    x.remove(m) 

このループの後に、x = ['b']。 しかし、なぜですか?

私が理解する限り、forキーワードは暗黙的にこのリストのイテレータを作成します。 .remove()__next__()メソッドなのでbはスキップされますか?私はそれについて言及することはできませんが、これは私の最高の推測です。

+2

ので、要素を削除するとポインタは更新されません。最後のインデックスは、反復によって保持されます。要素を変更すると、シフトされます。 –

+3

これは文書化された動作ではなく、実装固有のものです。避ける。ここで議論されています:https://unspecified.wordpress.com/2009/02/12/thou-shalt-not-modify-a-list-during-iteration/ – cdarke

+0

イテレータはおそらく 'i = 0一方、i

答えて

2

ここでは元のリストを反復しています。最初の繰り返しで、0thのインデックス要素、つまりaを削除しました。さて、あなたのリストは['b','c']です。 2回目の繰り返しでは、forループはインデックス1の値にアクセスしますが、インデックス1の値はcです。したがって、cは削除されます。したがって、結果リストは['b']になります。

期待通りに動作させるには、リストのコピーを繰り返し、元のリストから項目を削除します。

x = ['a','b','c'] 
for m in list(x): # <-- Here 'list(x)' will create the copy of list 'x' 
        # for will iterate over the copy 
    x.remove(m) 

# updated value of 'x' will be: [] 

:たとえばそれは、デモの目的のためではなく、あなたがリストを空にするため、このコードを使用している場合は、リストを空にする効率的な方法は次のようになります。

del x[:] 
+0

ありがとう! – Paul

+1

パフォーマンスの特性が悪いため、警告が必要です。リストの先頭から削除すると、残っているすべてのアイテムが1つ前に移動(コピー!)されます。リストが大きい場合は、パフォーマンスの影響が大きくなります。あなたのリストが5アイテム長い場合は、わずか10シフトになります。 1000アイテムであれば、499500シフトになります。 –

+0

はい、それは真です。あなたが望むのは、あなたのリストを空にすることだけです。 '、del x [:]'を実行します。回答の更新 –

関連する問題