Unexpected Behavior Iterating over a Mutating Object

Dave Hansen iddw at hotmail.com
Tue Sep 13 17:28:21 EDT 2005


OK, first, I don't often have the time to read this group, so
apologies if this is a FAQ, though I couldn't find anything at
python.org.

Second, this isn't my code.  I wouldn't do this.  But a colleague did,
got an unexpected result, and asked me why.  I think I can infer what
is occurring, and I was able to find a simple work-around.  But I
thought I'd ask about it anyway.

I've been pushing Python at work for use as a scripting language to
get simple tasks done.  My colleague is modifying a parts library for
a schematic capture program with a Python script.  The library is
entirely in ASCII text.  

He's trying to delete a group of parts from the library.  The simple
code below shows what is occurring (taken from an IDLE session, Python
2.4.1#65 for Windoze).  The "parts" to be deleted in the example
contain the string 'DEL':

---begin included file---
>>> data = [ 'First', 'Second DEL', 'Third', 'Fourth',
	     'Fifth DEL', 'DEL Sixth', 'Seventh DEL', 'Eighth DEL',
	     'Ninth DEL', 'Tenth', 'Eleventh', 'Twelfth']

>>> bfr = []
>>> for item in data:
	if item.find('DEL') >= 0:
		bfr.append(item)
		data.remove(item)

		
>>> data
['First', 'Third', 'Fourth', 'DEL Sixth', 'Eighth DEL', 'Tenth',
'Eleventh', 'Twelfth']
>>> bfr
['Second DEL', 'Fifth DEL', 'Seventh DEL', 'Ninth DEL']
---end included file---

It seems when an item is 'remove'd from data, the rest of the list
'shifts' over one, so what was 'next' now occupies the slot of the
'remove'd item.  When the next 'item' is selected from 'data', the
_desired_ 'next' item is skipped.  So when 'data' has several
consecutive items to be deleted, only every other one is 'remove'd.

The workaround is very simple:

---begin included file---
>>> for item in data:
	if item.find('DEL') >= 0:
		bfr.append(item)

		
>>> for item in bfr:
	data.remove(item)

	
>>> data
['First', 'Third', 'Fourth', 'Tenth', 'Eleventh', 'Twelfth']
>>> bfr
['Second DEL', 'Fifth DEL', 'DEL Sixth', 'Seventh DEL', 'Eighth DEL',
'Ninth DEL']
---end included file---

Again, iterating over an item that is mutating seems like a Bad
Idea(tm) to me.  But I was curious: is this the intended behavior, or
does this fall under what C programmers would call 'undefined
behavior.'

Thanks,

                               -=Dave
-- 
Change is inevitable, progress is not.



More information about the Python-list mailing list