Generators in Python!

Python generators code tutorial:

import string
import inspect

# Informal tutorial on the generators. We will cover very briefly:
## 1) What are the generators (PEP 255).
## 2) What is yield (PEP268).


# Generator in Python is a fancy object that maintain its state between calls. 
# In simple words generator knows what to return you next on a next function call. 
# And it doesn't need to store it in memory. 
# Think of it as a computation on-demand. Lazy, yeah. 
# Generator uses iterator protocol. 
# Thus it is common to say that every generator is an iterator. 
# It just means we can get a next value from the generator via next() call.
# You get a generator by asking to return one from a function. 

# Theoretically, you can compute something blah blah to 
# infinity using generators, and have very little memory footprint. 

# The 'yield' keywoard in a function will cause the function 
# instead of a value return a generator-iterator object. 


# Lets demonstrate!

# lets define a function that will return us a generator-iterator object 
# when we call it 
def english_alphabet_generator_function():
    for char in string.ascii_lowercase:
        yield char


print english_alphabet_generator_function 
# <function alphabet_generator at 0x1004c7320>, it is still a function


# Lets call english_alphabet_generator to get the actual generator object
alphabet_generator = english_alphabet_generator_function() 
# calling the generator function will return a generator-iterator object. 

print type(alphabet_generator) 
# <type 'generator'>, not a function anymore, we got generator object

# Now lets examine function locals - varibales defined in the function namespace 
print alphabet_generator.gi_frame.f_locals 
# {}, nothing yet 

# Now we can use iterator protocol and get print a few characters by calling generator's next() method. 
print alphabet_generator.next() # prints 'a'
print alphabet_generator.next() # prints 'b'
print alphabet_generator.next() # prints 'c'


print alphabet_generator.gi_frame.f_locals 
# prints {'char': 'c'}


# lets exauhst our generator and see what will happen
# it will print characters from d to y and throw 'StopIteration' exception
empty = False
while not empty:
    try:
        print alphabet_generator.next()
    except(StopIteration) as exp:
        empty = True
    
# Another not very useful example:
def _my_gen():
    for x in xrange(200, 400):
        yield 1

gen = _my_gen()
print("Sum:")
print(sum(gen)) # will print 200! :-) 


# Please, refer to 
# https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/ for a in-deep explanation with 
# very interesting examples. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *