2012-05-12 9 views
1

このコードでは、家族のリストを繰り返し、18歳以上の男性を特定し、家族から削除し、自分の家族を始めようとしています。ループの最後にappendをコメントアウトすると、(家族の数を増やすことなく)うまく動作します。これは私が追記行う場合のようにそれが見えるものです:リストに追加すると、なぜforループが壊れるのですか? (Python)

Ticking Disan 
There were 5 members of family Evnes 
Now there are 4 members of family Evnes 
Gregor needs a wife 
There were 6 families 
Now there are 7 families 
There were 7 members of family Bhworth 
Now there are 6 members of family Bhworth 
Ewan needs a wife 
There were 7 families 
Now there are 8 families 

debugger.run(setup['file'], None, None) 
    File "C:\Users\Mark\Desktop\eclipse-SDK-3.7.2-win32\eclipse\plugins\org.python.pydev.debug_2.5.0.2012040618\pysrc\pydevd.py", line 1060, in run 

pydev_imports.execfile(file, globals, locals) #execute the script 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 610, in <module> 
    main() 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 74, in main 
    done = menu() 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 77, in menu 
    genWorld() 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 116, in genWorld 
    dispWorld(oneWorld) 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 135, in dispWorld 
    displayTick(world) 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 317, in displayTick 
    calcMarriage(city) 
    File "C:\Users\Mark\workspace\WorldPop\WorldPop.py", line 359, in calcMarriage 
    for member in family.membersList: 
TypeError: iteration over non-sequence 

を、私は戻って最初にループサイクルのための新たなメンバーを検索するときに問題が来ることを認識し、私は、なぜ行って表示されていませんappendはループを壊しています。どんな洞察力も大変ありがとうございます。

+0

エラーを突き止めるために行番号を入力することはできますか?死に至る最後のラインはどれですか? ipythonのようなものを使って、データ構造の状態を調べることができますか? – Ansari

+1

まず、リストを反復してループ内から変更することは良い考えではないと思います。第二に、 'city.familyList.append(Family(member.lastName、member))'に新しい 'Family'を作成したときに' memberList'が何らかの理由で適切なリストではないと思われます。おそらく 'Family .__ init__'にバグがありますか? –

+0

ああ、通常、familyListはクラスオブジェクトの配列ですが、新しく作成されたファミリは1要素配列のクラスオブジェクトではなくクラスオブジェクトを受け取るだけです。 - これが問題だった!ありがとうございました! – CromerMW

答えて

1

一般的には、反復処理中のコレクションを変更することは本当に悪いことです(どちらもfamily.membersListから削除し、city.familyListに追加しています)。

反復処理中のデータ構造や反復アルゴリズムによっては、反復処理されたコレクションを変更すると、項目がスキップされるか、複数回表示されることがあります。私は、ドキュメントが明白にそうでないと言わない限り、これはほとんどの場合、安全ではないと思います。

+0

かなり安全ではありません。 –

+0

私が考えることができる例外の1つはリンクされたリストです。イテレーターが現在のリンクのみを保持している場合は、そのリンクを削除するか、前後に挿入してイテレーターを解除してはいけません。 –

2

追加する新しいFamilyインスタンスにはmembersList属性がありますが、反復(/ in)はサポートされていません。だからあなたはこの例外を受け取ります。

それを修正した後でも、シーケンスを反復処理している間にシーケンスを変更することで、驚きを自分で設定しています。これを試してみてください:それは、ループの開始時に存在しているよう

for family in city.familyList[:]: 
    for member in family.membersList[:]: 
     # ... 

[:]スライス構文は、各リストのコピーを作成します。元のリストに加えられた変更はコピーに影響しないので、ループ実行中に驚きはありません。 ループ中に見つかった/作成された新しいアイテムを実際にループに含める必要がある場合は、Queue.Queueオブジェクトを繰り返し処理し、各オブジェクトをそのキューに挿入することをお勧めします。探索するために何も新しいことがなければ、キューは空になり、ループは停止します。

関連する問題