Lazy Iterable

An iterable is an object that can return an iterator (__iter__).

In turn an iterator is an object that can return itself (__iter__), and return the next value when asked (__next__).

Lazy evaluation is when evaluating a value is deferred until it is actually requested.

It is not specific to iterables however.

Simple examples of lazy evaluation are often seen in classes for calculated properties.

Example

import math

class Circle:
    def __init__(self, r):
        self.radius = r
        
    @property
    def radius(self):
        return self._radius
    
    @radius.setter
    def radius(self, r):
        self._radius = r
        self.area = math.pi * r**2

every time we set the radius, we re-calculate and store the area. When we request the area of the circle, we simply return the stored value.

so we may take a hybrid approach where we want to store the area so we don't need to recalculate it every time (ecept when the radius is modified), but delay calculating the area until it is requested - that way if it is never requested, we didn't waste the CPU cycles to calculate it, or the memory to store

class Circle:
    def __init__(self, r):
        self.radius = r
        
    @property
    def radius(self):
        return self._radius
    
    @radius.setter
    def radius(self, r):
        self._radius = r
        self._area = None

    @property
    def area(self):
        if self._area is None:
            print('Calculating area...')
            self._area = math.pi * self.radius ** 2
        return self._area


c = Circle(1)

c.area
=> Calculating area...
=> 3.141592653589793

c.area
=> 3.141592653589793

c.radius = 2

=> Calculating area...
=> 12.566370614359172

        

Last updated