2012-05-12 58 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对象和插入每个对象研究该队列。当没有什么新的发现时,队列将是空的,循环将停止。