Skip to main content
3 of 3
edited tags; deleted 122 characters in body; edited tags
200_success
  • 144.2k
  • 22
  • 188
  • 473

Python lazy dictionary

Here is a lazy dictionary with test cases.

"""
A dictionary whose values are only evaluated on access.
"""
from functools import partial

from UserDict import IterableUserDict


class LazyDict(IterableUserDict, object):
    """
    A lazy dictionary implementation which will try
    to evaluate all values on access and cache the
    result for later access.
    """

    def set_lazy(self, key, item, *args, **kwargs):
        """
        Allow the setting of a callable and arguments
        as value of dictionary.
        """
        if callable(item):
            item = partial(item, *args, **kwargs)
        super(LazyDict, self).__setitem__(key, item)

    def __getitem__(self, key):
        item = super(LazyDict, self).__getitem__(key)
        try:
            self[key] = item = item()
        except TypeError:
            pass
        return item


def test_lazy_dict():
    """
    Simple test cases for `LazyDict`.
    """

    lazy_dict = LazyDict({1: 1, 2: lambda: 2})
    assert lazy_dict[2] == 2
    lazy_dict[3] = 3
    assert lazy_dict[3] == 3

    def joiner(*args, **kwargs):
        sep = kwargs.pop('sep', ' ')
        kwargs = [
            '%s=%s' % (k, v)
            for k, v in sorted(kwargs.iteritems())]
        return sep.join(list(args) + kwargs)

    lazy_dict.set_lazy(
        4, joiner, 'foo', 'bar', name='test', other='muah', sep=' ')
    assert lazy_dict[4] == 'foo bar name=test other=muah'

    assert lazy_dict.get('5') is None

    # Test caching functionality.
    def call_at_max(count):
        counter = [0]

        def inner():
            counter[0] += 1
            if counter[0] > count:
                raise AssertionError('Called more than once')
            return 'happy'
        return inner

    call_once = call_at_max(1)
    lazy_dict[5] = call_once
    assert lazy_dict[5] == 'happy'
    assert lazy_dict[5] == 'happy'

    # Test for helper function.
    try:
        call_once()
    except AssertionError:
        assert True
Justin Fay
  • 307
  • 2
  • 10