2012-05-12 112 views
1
for family in city.familyList: 
    for member in family.membersList: 
     if member.sex == "male": 
      if member.status == "eligible": 
       print "There were", len(family.membersList), "members of family", family.familyName 
       family.membersList.remove(member) 
       print "Now there are", len(family.membersList), "members of family", family.familyName 
       member.status = "needs a wife" 
       print member.firstName, member.status 
       print "There were", len(city.familyList), "families" 
       city.familyList.append(Family(member.lastName, member)) 
       print "Now there are", len(city.familyList), "families" 

有了這段代碼,我試圖遍歷一個家庭成員列表,找到18歲以上的男性,從他們的家庭中刪除他們,並開始他們自己的家庭。如果我在循環結束時註釋掉附加內容,它可以正常工作(當然,在不增加家庭數量的情況下)。這是什麼樣子,如果我執行追加:爲什麼追加到列表會中斷我的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 

我意識到,問題就來了,當爲循環週期回到開始通過新的會員搜索,我只是不明白爲什麼執行追加正在打破循環。任何見解都非常感謝。

+0

任何機會,你可以提供行號匹配的錯誤?最後一條線是死去的?你可以使用類似ipython的東西來查看它正在死亡的數據結構的狀態嗎? – Ansari

+1

首先,我不認爲迭代列表並從循環內改變列表是一個好主意。其次,我懷疑當你在'city.familyList.append(Family(member.lastName,member))'中創建一個新的'Family'時,由於某種原因它的'memberList'不是正確的列表。也許在'Family .__ init__'中有一個錯誤? –

+0

啊,是的,通常familyList是一個類對象的數組,而新創建的系列僅僅接收類對象,而不是一個元素數組中的類對象。 - 這是問題!謝謝! – CromerMW

回答

1

通常,修改要迭代的集合是一個非常糟糕的主意(您從family.membersList中刪除並添加到city.familyList)。

,具體取決於你遍歷數據結構,並在迭代算法,改變了迭代集合可能導致項目是要麼跳過或見過不止一次。我認爲這在大多數情況下都是不安全的,除非文檔明確地另有說明。

+0

它幾乎不安全。 –

+0

我能想到的一個例外是鏈接列表。如果迭代器只保存當前鏈接,那麼刪除該鏈接或在之前/之後插入不應該破壞迭代器。 –

2

您正在追加的新的Family實例具有membersList屬性,但它不支持迭代(for/in)。這就是爲什麼你收到這個例外。

即使是固定的是,你是通過修改序列和自己的驚喜,同時遍歷他們了。試試這個:

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

[:]切片語法創建每個列表的副本,因爲它存在於循環的開始。對原始列表所做的修改不會影響副本,因此在循環執行期間不會有任何意外。

如果你真的需要包括髮現/在for循環的循環for過程中創建新的項目,我建議遍歷一個Queue.Queue對象和插入每個對象研究該隊列。當沒有什麼新的發現時,隊列將是空的,循環將停止。