Search code examples
pythonlazy-initialization

Lazy class attribute initialization


I have a class that takes only one input argument. This value will then be used to compute a number of attributes (only one in the following example). What is a pythonic way if I wanted to take the computation place only if I call the attribute. In addition, the result should be cached and attr2 must not be set from outside the class.

class LazyInit:
    def __init__(self, val):
        self.attr1 = val
        self.attr2 = self.compute_attr2()

    def compute_attr2(self):
        return self.attr1 * 2  # potentially costly computation


if __name__ == "__main__":
    obj = LazyInit(10)

    # actual computation should take place when calling the attribute
    print(obj.attr2)

Solution

  • Make attr2 a property, not an instance attribute.

    class LazyInit:
        def __init__(self, val):
            self.attr1 = val
            self._attr2 = None
    
        @property
        def attr2(self):
            if self._attr2 is None:
                self._attr2 = self.compute_attr2()
            return self._attr2
    

    _attr2 is a private instance attribute that both indicates whether the value has been computed yet, and saves the computed value for future access.