Skip to content

Generators

Generators

Generators provide an efficient way to produce values one at a time without storing the entire sequence in memory.


Range vs List

range(100)

def make_list(num):
    result = []
    for item in range(num):
        result.append(item * 2)
    return result

print(make_list(100))       # Using a custom function
print(list(range(100)))     # Using built-in range

Use a generator and actually generate these, without taking space in memory.

Iterables vs Generators

  • Iterable → any object you can loop over.
    It has a dunder iter method.(iter)

  • Generator → a special type of iterable created with yield.

  • Everything that is a generator is iterable.

  • You can iterate over them, but not everything that is iterable is a generator. range is a generator list is an iterable, but not a generator
  • So generator is a subset of an iterable

Creating a Generator

def generator_func(num):
    for i in range(num):
        yield i             #a generator uses yield instead of return to make a generator

g = generator_func(1)
next(g)                     #if the range is out of num it gives error of stop iteration
print(next(g))              #can call generator with next, while iterating

for i in generator_func(1):
    print(i)

yield returns values one at a time. next() retrieves the next value until StopIteration is raised.

Implementing a Custom For Loop

def special_for(iterable):
    iterator = iter(iterable)
    while True:
        try:
            print(iterator)
            print(next(iterator))
        except StopIteration:
            break

special_for([1,2,3])            #the list is stored at same memory place

Custom Generator Class(range function)

class MyGen():
    current = 0
    def __init__(self, first, last):
        self.first = first
        self.last = last

    def __iter__(self):
        return self

    def __next__ (self):
        if MyGen.current < self.last:
            num = MyGen.current
            MyGen.current += 1
            return num
        raise StopIteration

gen = MyGen(0,100)
for i in gen:
    print(i)