Handy utility to build caching properties in your classes.
    Decorated code will be run only once and then result will be stored in private class property
    with the given name. When called for the second time, property will return cached value.


    :param storage_var_name: Name of the class property to store cached data.
    :type storage_var_name: str
    :return: Decorator for the class property

def cached_property():
    """
    Handy utility to build caching properties in your classes.
    Decorated code will be run only once and then result will be stored in private class property
    with the given name. When called for the second time, property will return cached value.


    :param storage_var_name: Name of the class property to store cached data.
    :type storage_var_name: str
    :return: Decorator for the class property
    """
    def _stored_value(f):
        storage_var_name = "__{}".format(f.__name__)

        def _wrapper(self, *args, **kwargs):
            value_in_cache = getattr(self, storage_var_name, Sentinel)
            if value_in_cache is not Sentinel:
                return value_in_cache
            calculated_value = f(self, *args, **kwargs)
            setattr(self, storage_var_name, calculated_value)
            return calculated_value
        return _wrapper
    return _stored_value