import functools


def lazy_property(fn):
    """A property decorator that caches the returned value."""
    key = fn.__name__ + "_cache_val_"

    @functools.wraps(fn)
    def _lazy(self):
        """Very simple cache."""
        if not hasattr(self, key):
            setattr(self, key, fn(self))
        return getattr(self, key)

    return property(_lazy)