def cached_method(method: TFunc | None = None, *, maxsize: int = 128) -> Any:
    """Decorator that adds a per-instance LRU cache for a method.

    Can be applied with or without parameters to customize the underlying cache:

        @cached_method
        def foo(self, name: str) -> int:
            ...

        @cached_method(maxsize=1000)
        def bar(self, name: str) -> int:
            ...
    """

    def decorator(func):
        cache_name = _method_cache_name(func)
        signature = inspect.signature(func)

        if len(signature.parameters) == 1:
            # Optimization in the case where the method takes no arguments other than `self`.

            @functools.wraps(func)
            def wrapped_no_args(self):
                result = getattr(self, cache_name, _NOT_FOUND)
                if result is _NOT_FOUND:
                    result = func(self)
                    object.__setattr__(self, cache_name, result)
                return result

            return wrapped_no_args

        @functools.wraps(func)
        def wrapped(self, *args, **kwargs):
            cached = getattr(self, cache_name, None)
            if cached is None:

                @functools.lru_cache(maxsize=maxsize)
                def cached_func(*args, **kwargs):
                    return func(self, *args, **kwargs)

                object.__setattr__(self, cache_name, cached_func)
                cached = cached_func
            return cached(*args, **kwargs)

        return wrapped

    return decorator if method is None else decorator(method)
Decorator that adds a per-instance LRU cache for a method.

    Can be applied with or without parameters to customize the underlying cache:

        @cached_method
        def foo(self, name: str) -> int:
            ...

        @cached_method(maxsize=1000)
        def bar(self, name: str) -> int:
            ...
    
cirq-core/cirq/_compat.py