def cached_property(func):
    """Return a cached property calculated by the input function.

    Unlike the 'property' decorator from the standard library, this decorator
    will cache the return value in order to avoid repeated calculations. This
    is particularly useful when the property involves some non-trivial
    computation.
    """
    def get(self):
        """this docstring will be over-written by func.__doc__"""
        try:
            return self._property_cache[func]
        except AttributeError:
            self._property_cache = {}
            prop = self._property_cache[func] = func(self)
            return prop
        except KeyError:
            prop = self._property_cache[func] = func(self)
            return prop
    get.__doc__ = func.__doc__
    return property(get)