[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()
0
>>> for x in iterlst:
... if x < 5:
... print x
... else:
... break
...
1
2
3
4
>>> for x in iterlst:
... print x
...
6
7
8
9
#####
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.
Thanks,
Eric
More information about the Tutor
mailing list