import functools


def lazy_property(function):
    """Decorator which adds lazy evaluation to the function and cashing the result.

    Parameters
    ----------
    function : callable
        The function that should be evaluated only once and providing the
        result that gets cached.

    Returns
    -------
    return type of callable
        The cached result from the first and only evaluation.

    """
    attribute = '_cache_' + function.__name__

    @property
    @functools.wraps(function)
    def decorator(self):
        if not hasattr(self, attribute):
            setattr(self, attribute, function(self))
        return getattr(self, attribute)

    return decorator