import functools


def cached_method(cache_size=100):
    """
    Decorator to cache the output of class method by its positional arguments
    Up tp 'cache_size' values are cached per method and entries are remvoed in a FIFO order
    """

    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(self, *args, **kwargs):
            _dict = self._cached_methods[fn.__name__]
            if args in _dict:
                return _dict[args]
            res = fn(self, *args, **kwargs)
            if len(_dict) >= cache_size:
                _dict.popitem(False)
            _dict[args] = res
            return res

        return wrapper

    return decorator