"For" statements in Python internally create iterators that are used to step through the provided sequence.
Python exposes this iteration capability with the "iter()" function. You can pass any kind of collection to "iter" and it returns an iterator object, from which you can call "next()" to retrieve the next element in the collection.
>>> it = iter([1,2,3]);
Not only that, but you can define some functions in your classes that gives other people the ability to call "iter" on an instance of your class. You can define the function "__iter__" and it must return another object that contains the function "next." It's typical to contain both these functions in the class and simply return itself when "__iter__" is called.
Python provides a more compact way of creating iterators. A generator is a normal function except it has the keyword "yield" in it. "Yield" is used when you want to return data. Each time next() is called, the function resumes where it left off (from the yield statement). It's basically a function that automatically creates the "__iter__" and "next" functions for you.
>>> def fRange():
for i in range(5):
>>> for j in fRange():
In journal #6 I described the cool technique of implicity generating sequences. It's derived from generators, and they are called "generator expressions." This way you don't even have to define a function, you can tell Python to automatically generate a sequence according to some iteration.