def instance_cache(func):
    """Cache the result of a method on a per instance basis.

    This is not a general purpose caching decorator. In order for this to be used,
    it must be used on methods on an instance, and that instance *must* provide a
    ``self._cache`` dictionary.

    """
    def _wrapper(self, *args, **kwargs):
        key = (func.__name__,) + args
        for pair in sorted(kwargs.items()):
            key += pair
        if key in self._cache:
            return self._cache[key]
        data = func(self, *args, **kwargs)
        self._cache[key] = data
        return data
    return _wrapper