Iterators are efficient way of traversing over collection of items in python. However to create a iterator we need to implement class with special functions, manage state of class and raise an exception to indicate end of iteration. Its lot of work and complex for small task like generating Fibonacci series.But, You know what?, Python is not made for complexity as per zen of python. There is simpler method for creation of iterators and they are called mighty GENERATORS.

Recommended Reading : Iterable and Iterator in Python

Generators are special kind of function which simplifies the creation of iterator. They are just functions with yield keyword instead of return. On invoking such function, it returns a generator object which we can iterate over. Oh!! it sounds so confusing. lets see an example to clear things out.

In above example, we have created a simple iterator class to count down up to 0. To see its output, lets put it in for loop.

Now here comes generator.

Only four lines of code.On iterating and printing the number we get:

What’s happening here?

Functions with one or more yield keywords are treated as generator in python. Whenever we call a generator function , it returns us a generator object. However, statements inside a function are not yet executed at this point. Function only executes after calling next() function of generator object. Don’t believe me? check it out.

After we invoke this normal function, we get:

Notice that it prints that string. If we replace that return with yield we get:

And after invoking the function.

No printed string right? That means it just returned object without even beginning execution of the function. Naughty python.

If we iterate one step using next() we get:

Hola! finally first statement inside function gets executed. Here we found that When next method is called for the first time, function executes until it reaches yield statement then freezes. And resumes from where it left on calling same next() function next time and saves its state again. and the cycle goes on. Let’s keep calling next() and see what happens.

Where did that exception come from?

Its implemented by default in generator . Iterator protocol requires iterator to raise an exception to indicate end of iteration. And generator does this for us. Lets see another example here.

This example clearly shows us the pause-resume nature of generator. Using this pause-resume method generator tracks its state. And it raises an exception on exiting function other than with yield key word. In this way generator complies with iterator protocol.

Are Generator And Iterator Same?

Generator is a subclass of iterator.

We can say that every Generators are Iterator but not vice-versa.

Generator Comprehensions (Generator Expression).

Generator comprehension is exactly like list comprehensions but with lazy mode on.

See also: Comprehensions in python

It’s syntax is:

The difference between list comprehension and generator comprehension is enclosing parentheses instead of square bracket.

If we we run this command:

But with generator comprehensions:

It only generates output on demand. Which can be verified with.

We should remember few things while implementing generator in python. Unlike iterable, we can iterate over generator only once. Generally, we can not put same generator object in two complete(no break inside loop) for loops.

To use with another for loop we have to recall generator function or reassign generator expression.

Generators are little slower compared to list comprehensions because of function overhead associated. But clean syntax , ease of use and lazy evaluation make generators perfect for creation of iterators.