Signup/Sign In
LAST UPDATED: DECEMBER 6, 2019

Generators in Python - Part 1

    When an iterator is used in Python, it results in overhead, which sometimes may prove to be not-so time-effective. This is because when an iterator is used, the __iter__ and the __next__ methods need to be implemented in a class. In addition to this, a tab needs to be kept on the internal states and a StopIteration error needs to be raised when no value is returned from the iterator.

    This is where a generator comes into play and has an upper hand when it comes to performace and maintaining state.

    A generator is one of the simplest ways to create iterators which can maintain state. Instead of us keeping a tab on the various processes, the generator automatically handles all the overhead for us. It is a method (function) that iterates over an iterable and returns a generator object. They can be put into use by calling the next method on a generator object or a for loop.




    Creating a generator in Python

    The process of creating a generator function is a simple process. If a function contains at least one yield statement, it is considered to be a generator function. In addition to containing one yield statement, it can contain other return or yield statements as well. The return value from yield and return are the same. The only difference between the yield and return statements is that the yield statement pauses the method and saves all the states, later continuing the execution from the last saved state whereas the return statement terminates the method in its entirety.


    Time for an example:

    The below example creates a generator method (since it has a yield statement) and runs a for loop to print the value by calling the generator function.

    def GeneratorMethod(x): 
        yield x            
    
    for value in GeneratorMethod(12):  
        print(value) 

    Output:

    12



    Using the next method with generators

    The below example shows how the generator function can be created and used in conjunction with __next__ method. It also shows how the for loop can be used with the generator method.


    Time for an example:

    def fibonacci_seq(value): 
        a, b = 0, 1
      
        while a < value: 
            yield a 
            a, b = b, a + b 
      
    x = fibonacci_seq(4)   # creating a generator object 
    print("Using _next__()")  
    print(x.__next__());
    print(x.__next__());
    print(x.__next__());
    print(x.__next__());
    
    print("\n")
    print("Using for loop with generator") 
    for i in fibonacci_seq(4):  
        print(i) 

    Output:

    Using _next__()
    0
    1
    1
    2
    
    Using for loop with generator
    0
    1
    1
    2
    3



    Differences between a generator function and a normal function

    • The generator function returns using a yield statement.

    • The __iter__ and __next__ methods are implemented automatically in generator methods. It can be iterated over using the __next__ method.

    • It returns a generator object but doesn't start execution right afterward.

    • Once the yield statement is executed inside the generator method, the function is paused and the control gets transferred to the caller.

    • The state of the local variables is remembered between 2 successive calls.

    • The StopIteration is automatically called when the function gets terminated.


    Application of generators in Python

    Used in stream processing to handle large data files which could potentially be log files.


    Conclusion

    In this post, we understood the importance of generators, creating a generator and the differences between a generator method and a normal method. Don't forget to execute the code in IDE and meddle with the code.

    I love writing about Python and have more than 5 years of professional experience in Python development. I like sharing about various standard libraries in Python and other Python Modules.
    IF YOU LIKE IT, THEN SHARE IT
    Advertisement

    RELATED POSTS