2016-07-13 10 views
3

私が持っている重みリストの異なる順列を生成し、すべての順列を外側リストに追加したいとします。このコードは正しく並べ替えを生成しますが、外側のリストに追加しても、最後に印刷すると空になります。再帰関数のリストに追加される値へのアクセス

リストが変更可能なので、これは参照によって呼び出されたと考えました。そのため、関数のリストに加えられた変更は、関数の範囲外にも反映されます。

このコードを修正すると、外側のリストには、各パーミュテーションがリストの外にある関数の外にすべての置換が含まれますか?

weight = [100,120,140] 
outer_list = [] 
def func(outer_list,inner_list,weight,i,max_val): 
    if len(inner_list) == max_val: 
     print inner_list 
     outer_list.append(inner_list) 
     return 
    inner_list.append(weight[i]) 
    func(outer_list,inner_list,weight,i,max_val) 
    del inner_list[-1] 
    for j in range(i+1,len(weight)): 
     inner_list.append(weight[j]) 
     func(outer_list,inner_list,weight,i,max_val) 
     del inner_list[-1] 


inner_list = [] 
func(outer_list,inner_list,weight,0,2) 
print outer_list 

電流出力:

[100, 100] 
[100, 120] 
[100, 140] 
[120, 100] 
[120, 120] 
[120, 140] 
[140, 100] 
[140, 120] 
[140, 140] 
[[], [], [], [], [], [], [], [], []] 

答えて

4

あなたはリストが変更されていることが正しいです。あなたが忘れてしまったことの1つ:inner_listouter_listを追加しましたが、最初にコピーしませんでした。まだ変更可能で、追加したinner_listはすべて同じオブジェクトです。代わりにコピーを使用してください:

 outer_list.append(inner_list[:]) 

[:]はスライスです。スタートを外したので、デフォルトは最初です。ストップを外したので、デフォルトになります。したがって、リスト全体をスライスして、浅いコピーを作成しました。

この場合、浅いコピーが必要ですが、inner_listにも変更の対象となる変更可能なオブジェクトが含まれている場合は、詳細コピーが必要です。ディープコピーを取得するには、copy.deepcopy() functionを使用します。

+0

良いキャッチ!私は認めます、私はこの1つを困惑しました。ああ、状態データと可変データの落とし穴... –

+0

'[:]'は浅い*コピーしか作成しないことをあなたの投稿で指摘しておく価値があります。この特定の質問には問題はありませんが、将来この問題に遭遇し、ネストされたデータ構造を持つ他の人々に情報を含めるべきだと思います。 –

+1

@PierceDarragh:これは確かに指摘しておく価値があり、現在はポストに入っています。 – zondo

関連する問題