[Tutor] __iter__ loops, partitioning list among children

Eric Abrahamsen eric at ericabrahamsen.net
Tue Aug 26 19:24:16 CEST 2008

On Aug 26, 2008, at 7:20 PM, Kent Johnson wrote:

> On Tue, Aug 26, 2008 at 1:36 AM, Eric Abrahamsen
> <eric at ericabrahamsen.net> wrote:
>> So my test case: a Month has a 'child' attribute pointing at Week,  
>> which has
>> a 'child' attribute pointing at Day, so they all know what kind of  
>> child
>> instances iteration should produce. With nested loops, a Month  
>> produces one
>> Week, that Week produces seven Days, then the next Week is  
>> produced, it
>> makes seven more Days, etc. That much is easy.
> If all you want to do with the nested Month, etc is to iterate the
> events in them, you could probably use a shared iterator. It would
> have to be able to push-back items so that when you hit the
> out-of-range item you could push it back on the iterator.

Is a 'shared iterator' something special, or do you mean all the  
instances would draw their events from a single iterator? I'm not sure  
what this would look like.

>> Then there's self.events. My original code looped over all of  
>> self.events
>> for each child produced. A Month loops over its events four times,  
>> a Week
>> seven times. This was the straightforward implementation, but it  
>> seemed
>> inefficient. (I also, as you point out, might have been wrong about  
>> the way
>> django QuerySets work). My thought was that only one loop over  
>> self.events
>> should be necessary, in theory, since they're sorted by date.
> Instead of direct use of the list iterator, you could pass the list
> and the starting index around. Then you don't have to keep finding
> your place.

That's a definite possibility, I'll try it out. Itertools.tee is also  
something I've yet to look at closely. Thanks for these hints.

>> A for loop creates an iterator from a sequence and calls next() on  
>> it, and
>> it creates an entirely new iterator each time you start a new for  
>> loop:
> I still don't understand your code but you may have another
> misconception. Calling iter() on an iterator returns the same
> iterator; it does not make a new iterator that holds the same place.
> You can use itertools.tee() to split an iterator if that is what you
> want to do.

Just for the sake of argument, here's the principle I'm working from:

 >>> lst = range(10)
 >>> iterlst = iter(lst)
 >>> iterlst.next()
 >>> for x in iterlst:
...   if x < 5:
...     print x
...   else:
...     break
 >>> for x in iterlst:
...   print x

So that's why I'm creating the iterator outside of the while loop in  
the original code, and then using a repeated for loop with a break to  
step through all the events only once. Of course, the fact that 5  
isn't in there probably points to the source of my problems! The  
solution might be assigning iterlist.next() to a variable, and  
advancing the variable.


More information about the Tutor mailing list