Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #60762

Re: For-each behavior while modifying a collection

Path csiph.com!usenet.pasdenom.info!news.etla.org!news.stack.nl!newsfeed.xs4all.nl!newsfeed2.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail
Return-Path <python-python-list@m.gmane.org>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.000
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; '(at': 0.04; 'element': 0.07; 'modify': 0.07; 'removes': 0.07; 'suppose': 0.07; 'iterate': 0.09; 'pointless': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'subject:while': 0.09; 'wrong,': 0.09; 'def': 0.12; 'creates': 0.14; '10:49': 0.16; 'be:': 0.16; 'collections': 0.16; 'complicated,': 0.16; 'element,': 0.16; 'expression,': 0.16; 'incremented': 0.16; 'iterables': 0.16; 'iteration': 0.16; 'iteration.': 0.16; 'iterator': 0.16; 'iterator,': 0.16; 'least)': 0.16; 'loops': 0.16; 'objects.': 0.16; 'received:80.91.229.3': 0.16; 'received:dyn.optonline.net': 0.16; 'received:optonline.net': 0.16; 'received:plane.gmane.org': 0.16; 'two.': 0.16; 'uses,': 0.16; 'elements': 0.16; 'index': 0.16; 'wrote:': 0.18; 'value.': 0.19; 'examples': 0.20; 'written': 0.21; '>>>': 0.22; 'memory': 0.22; 'example': 0.22; 'header:User- Agent:1': 0.23; 'entries': 0.24; 'looks': 0.24; 'references': 0.26; 'this:': 0.26; 'code:': 0.26; 'values': 0.27; 'header:X -Complaints-To:1': 0.27; 'header:In-Reply-To:1': 0.27; 'function': 0.29; 'am,': 0.29; 'list:': 0.30; 'statement': 0.30; 'along': 0.30; "i'm": 0.30; 'url:mailman': 0.30; 'ist': 0.31; 'about.': 0.31; 'implicit': 0.31; 'modified,': 0.31; 'url:python': 0.33; 'running': 0.33; 'are:': 0.33; 'not.': 0.33; 'copying': 0.34; 'sense': 0.34; 'could': 0.34; 'advice': 0.35; 'point.': 0.35; 'but': 0.35; 'there': 0.35; 'acceptable': 0.36; 'explains': 0.36; 'whilst': 0.36; 'done': 0.36; 'url:listinfo': 0.36; 'url:org': 0.36; 'should': 0.36; 'list': 0.37; 'clear': 0.37; 'performance': 0.37; 'to:addr:python-list': 0.38; 'list,': 0.38; 'pm,': 0.38; 'does': 0.39; 'bad': 0.39; 'though,': 0.39; 'to:addr:python.org': 0.39; 'received:org': 0.40; 'url:mail': 0.40; 'how': 0.40; 'even': 0.60; 'prices': 0.60; 'most': 0.60; 'length': 0.61; 'new': 0.61; "you're": 0.61; 'more': 0.64; 'different': 0.65; 'reads': 0.68; 'reverse': 0.68; 'subject:For': 0.78; 'batchelder': 0.84; 'duplication': 0.84; 'mechanics': 0.84; 'careful': 0.91
X-Injected-Via-Gmane http://gmane.org/
To python-list@python.org
From Ned Batchelder <ned@nedbatchelder.com>
Subject Re: For-each behavior while modifying a collection
Date Fri, 29 Nov 2013 07:04:07 -0500
References <CAO5g_efLUD9kJ_W+fBUWv=9yrDggN2560H5Fx3uUVDQ=oAVREg@mail.gmail.com> <l77u09$30r$1@ger.gmane.org> <52977C71.4010200@mrabarnett.plus.com> <CAO5g_ee7qCLrrJ8ir13nLF1S=HPPDhawRAeDjN3vgstPcG-psg@mail.gmail.com>
Mime-Version 1.0
Content-Type text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding 7bit
X-Gmane-NNTP-Posting-Host ool-4356373c.dyn.optonline.net
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Thunderbird/24.1.1
In-Reply-To <CAO5g_ee7qCLrrJ8ir13nLF1S=HPPDhawRAeDjN3vgstPcG-psg@mail.gmail.com>
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.15
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.3396.1385726660.18130.python-list@python.org> (permalink)
Lines 102
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1385726660 news.xs4all.nl 15884 [2001:888:2000:d::a6]:49198
X-Complaints-To abuse@xs4all.nl
Xref csiph.com comp.lang.python:60762

Show key headers only | View raw


On 11/28/13 5:14 PM, Valentin Zahnd wrote:
> 2013/11/28 Ned Batchelder <ned@nedbatchelder.com>:
>> On 11/28/13 10:49 AM, Valentin Zahnd wrote:
>>>
>>> Hello
>>>
>>> For-each does not iterate ober all entries of collection, if one
>>> removes elements during the iteration.
>>>
>>> Example code:
>>>
>>> def keepByValue(self, key=None, value=[]):
>>>       for row in self.flows:
>>>           if not row[key] in value:
>>>               self.flows.remove(row)
>>>
>>> It is clear why it behaves on that way. Every time one removes an
>>> element, the length of the colleciton decreases by one while the
>>> counter of the for each statement is not.
>>> The questions are:
>>> 1. Why does the interprete not uses a copy of the collection to
>>> iterate over it? Are there performance reasons?
>>
>>
>> Because implicit copying would be pointless in most cases.  Most loops don't
>> even want to modify the collection, why copy all iterables just in case your
>> loop might be one of the tiny few that might change the collection?
>>
>
> Okay, I get this point.
> But how is the for-each parsed. Is it realised with a iterator or ist
> done with a for loop where a counter is incremented whilst it is less
> than the length of the list and reads the element at the index of the
> counter?

The for loop creates an iterator over the expression, and pulls values 
from the iterator, running the body once for each value.

This presentation explains the mechanics of loops, along with some 
examples of more exotic uses, and (at least) one bad joke: 
http://nedbatchelder.com/text/iter.html

>
>> Of course, if that prices is acceptable to you, you could do the copy
>> yourself:
>>
>>      for row in list(self.flows):
>>          if row[key] not in value:
>>              self.flows.remove(row)
>>
>>
>>> 2. Why is the counter for the iteration not modified?
>>
>>
>> Because the list and the iterator over the list are different objects. I
>> suppose the list and the iterator could have been written to update when the
>> list is modified, but it could get pretty complicated, even more so if you
>> want to do the same for other collections like dictionaries.
>>
>> The best advice is: don't modify the list, instead make a new list:
>>
>>      self.flows = [r for r in self.flows if r[key] not in value]
>>
> How is the list comprehension done by the interpreter?
> The list I'm have to work with is not that small. So to avoid
> duplicated parts in memory the function looks currently like this:
>
>       def keepByValue(self, key=None, value=[]):
>           tmpFlows = []
>           while len(self.flows) > 0:
>               row = self.flows.pop()
>               if row[key] in value:
>                   tmpFlows.append(row)
>           self.flows = tmpFlows
>
> If there is no duplication in memory, the list comprehension would be
> much more elegant.
>

The list comprehension won't copy the elements of the list, if that is 
what you're worried about.  And it won't reverse the order of your list 
the way this loop does.  BTW, my list comprehension got the sense of the 
condition wrong, it should be:

     self.flows = [r for r in self.flows if r[key] in value]

--Ned.

>> Be careful though, since there might be other references to the list, and
>> now you have two.
>>
>> --Ned.
>>
>>>
>>> Valentin
>>>
>>
>>
>> --
>> https://mail.python.org/mailman/listinfo/python-list

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: For-each behavior while modifying a collection Ned Batchelder <ned@nedbatchelder.com> - 2013-11-29 07:04 -0500

csiph-web