-> What are generators?

    Generators are used to generate range of values
    without using extra space.

    for example, range(1,100) creates number from 1 to
    100 but in this the procedure is as follows:

    -> initialize with value 1.
    -> returns the value.
    -> increment it by one.
    -> Repeat this same process from step 2,
        until all values are generated with
        the given range.


    * generators is a iterator but iterator
     is not necessarily a generator.

-> How to create your own generators?

    for ex:

        def generator_function(num):
            for i in range(num):
                yield i

        g = generator_function(10)
        next(g)
        next(g)
        print(next(g))

    Two keywords are used here:
    -> yield: This is used to make functions a
                generator.

    -> next: This is used to get the next value from
            generator function

    Note that unlike creating a list and then returning
    the range of values, generators don't take extra 
    space to have range of values.