Help on for loop understanding

Erik python at lucidity.plus.com
Mon Dec 7 21:36:00 EST 2015


On 08/12/15 01:50, Robert wrote:
> One example, see below please, is in the above mentioned link. I don't see
> the purpose of the example.

OK, so there are two parts to this.

The first, is "how do I iterate over something". The answer to that is 
using "for" or using "iter()" followed by zero or more calls to 
"next()". In this case, by using the correct syntax/function calls your 
script can work under various versions of Python without change.

The second is "how do I make my own classes iterable". This is what the 
example you pasted is trying to show. In this case, you are implementing 
things which are "internal" to the way the version of Python you are 
using does things (which is why the code Robin posted wasn't quite right 
for you).

> I have the following two same results. What do they tell me?

They tell you that the implementation does the same thing as the default 
implementation for a list. That perhaps doesn't help much - especially 
with the comment in the example telling you not to do it!

Instead, try the following (Python 2):

class MyList(list):
     def __iter__(self):
         return MyListIter(self)

class MyListIter(object):
     def __init__(self, lst):
         self.lst = lst
         self.i = -1

     def __iter__(self):
         return self

     def next(self):
         if self.i >= -len(self.lst):
             item = self.lst[self.i]
             self.i -= 1
             return item

         raise StopIteration

if __name__ == "__main__":
     a = MyList([1, 2, 3, 4])
     ia = iter(a)
     print 'type(a): %r, type(ia): %r' %(type(a), type(ia))
     for i in a:
         print i,
     print

     while True:
         print next(ia)

What we have here is the same class that subclasses 'list'. It's just a 
list. However, it has a custom iterator. In this implementation the 
iterator works BACKWARDS through the list - the final element is 
returned first, the penultimate element second, and so on. After the 
first element has been returned, the iterator raises StopIteration. This 
tells you not to call next() again, or if in a for loop, the loop is exited.

So, you can write your class's iterator to do anything that makes sense 
when someone says "for i in myclassinstance:".

If your class is a subclass of a class ("is-a") that already has a 
defined iterator (such as a list or a dict) and the behaviour of that is 
correct for you, then you need to do nothing (you inherit that class's 
__iter__() method).

If your class should iterate over an embedded object ("has-a") that 
already has a defined iterator, then your __iter__() method can just 
delegate to that object's iterator using something like:

def __iter__(self):
     return iter(self.embedded_thing)

Does that make more sense?
E.



More information about the Python-list mailing list