2016-04-13 5 views
1

私はここ6位上の2つの可能な結果のすべての可能な配列を生成しています:すべて含むリストの一つの要素である再割り当ての動作はどのように現れますか?

(['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax',  
'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0]) 

:それは生成する必要があり何

paths = list(it.product([['ax','r',[],0], ['ax','l',[],0]], repeat=6)) 

のようなものです結果。

私はこのような何か書いて繰り返しパターンこのため
'yp', 'p', 'xp'

によると、今「斧」の文字列を変更したい:結果は何かであるしかし

for path in paths: 
    axis = 1 
    for axis_slice in path: 
     if(axis%3 == 1): 
      axis_slice[0] = 'yp' 
      print(axis_slice[0]) 
     elif(axis%3 == 2): 
      axis_slice[0] = 'p' 
      print(axis_slice[0]) 
     elif(axis%3 == 0): 
      axis_slice[0] = 'xp' 
      print(axis_slice[0]) 
     axis+=1 
    print("axis: "+str(axis)) 
    print(path) 

(['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0]) 

ただし、上記の行のprint-statementは正しく表示されていますまだバック1 'レベル' 代入( 'YP'、 'P'、 'XP')

yp 
p 
xp 
yp 
p 
xp 
axis: 7 
(['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0]) 

がどのようにこの動作が出現しない発散を行く、ssigned?内側のループでは表示されませんが、外側のループでは表示されないのはなぜですか?評価の順序やタプル/リストのパック方法と関係があるかもしれません。

どのように目的の出力を達成できますか?

+0

編集のためのBhargav Raoさんありがとうございます。私は今後の投稿の間違いを避ける! – Daniyal

+0

ああ、確かに、ここのstackoverflowのインデントは間違っていました。ヒントありがとう!元のソースでは、インデントは正しいです:)パスについて:各パスは、タプル要素としてのリストのタプルです。うん、リストは変更可能ですが、タプル(afaik)はそうではありません:) – Daniyal

+1

ちょっと考えました。'itertools.product'で厳密なリストを使うことはできませんし、' repeat'を減らしてインデクシングの仕事がないようにしてください。 –

答えて

1

内のリストのすべてのメンバーがpathsにあるのは同じオブジェクトです。これを確認するには -

import itertools as it 
paths = list(it.product([['ax','r',[],0], ['ax','l',[],0]], repeat=6)) 
for path in paths: 
    print([id(p) for p in path]) 

これは、パス内の各リストの一意の識別子を表示します。 it.productに渡された元の2つのリストのIDは、2つのIDのみを持つことがわかります。

あなたが最初のパス取るのであれば、例えば、:

(['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0]) 

を実際に同じリストに6つの参照のタプルです。したがって、それらを反復するにつれて、毎回同じリストが変更されます。 axis_slice[0]の代わりにprint(path)を変更すると、何が起きているのかが明確にわかります。pathの全員が毎回変更されます。これはリストの変更可能性の機能であり、変更可能なメンバーを持つリストにitertools.productを使用しています。

この効果は、PythonとSOベテランのNed Batchelder hereによって実際によくカバーされています。特に、 - 記事全体が本当に読む価値はあるが、 "Mutable aliasing"と以下のスライドを見てください。

この問題を回避する方法は、このコードのコンテキストに大きく依存します。

+0

優秀な説明。また、この効果に関する多くのおかげです。このケースでは、Jリチャード・スネイプとCパンダに感謝します。 – Daniyal

関連する問題