Lazy Dictionaries

In a language like Python, not many things are lazy evaluated by nature, as opposed to a language like Haskell where everything is lazy by nature. Python does have generators that provide lazy iterations, but it is easy to also create lazy dictionaries and other data structures.

Lazy evaluation in code gives you the ability to postpone code execution until it is required, and sometimes it is not executed at all. It also has the potential to make code slower if everything is evaluated, but that is another discussion. Lazy dictionaries are useful for building data structures that may be used for more than one purpose such as a rendering context for a template. Here is a very contrived example:

class LazyDict(dict):
    def __getitem__(self, y):
        val = dict.__getitem__(self, y)
        if callable(val):
            val = val()
            self[y] = val
        return val

In this example, if a dictionary's value is callable, the called result is stored as the key. Here is an example of the usage:

>>> import uuid
>>> d = LazyDict()
>>> d['item'] = lambda: str(uuid.uuid4())
>>> print d['item']

The uuid doesn't actually get generated until d['item'] is accessed on the print line. The reason is that since it is wrapped in the lambda, the code is not pre-evaluated to store in the dict. Instead, the function object itself is stored in the dict and later called. The function retains access to all items surrounding its scope, such as the uuid function. Note that this could lead to memory references to unexpected objects if the lambda is never evaluated.

For resources such as complex calculations or database queries, lazy evaluation is a very useful tool to ensure that things only happen if they need to. LazyDicts could contain functions as values that generate other LazyDicts down the line.

In the example above, any callable would be called, but in reality a special class such as a Deferred class to wrap the callable and state might be more useful. Otherwise any arbitrary code could be stored in the value and would be executed, which could be potentially dangerous if used incorrectly (and could cause errors are very hard to track down to to their dynamic nature). But used properly, lazy structures in python are a very useful tool.