"""
Write a function that accepts another function as an argument. Then it
should return such a function, so the every call to initial one
should be cached.


def func(a, b):
    return (a ** b) ** 2


cache_func = cache(func)

some = 100, 200

val_1 = cache_func(*some)
val_2 = cache_func(*some)

assert val_1 is val_2

"""
from typing import Callable


def cache(func: Callable) -> Callable:
    cacher = dict()

    def wrap(*args, **kwargs):
        kwags_values = tuple(kwargs.values())
        if (args, *kwags_values) not in cacher:
            cacher[(args, *kwags_values)] = func(*args, **kwargs)

        return cacher[(args, *kwags_values)]

    return wrap
