# Écrire le code pour la fonction cache. C'est un décorateur qui doit # se souvenir de ce que la fonction décorée a renvoyé, et retourner la valeur mémorisée # lors d'un appel ultérieur avec les mêmes arguments. # On peut supposer que tous les arguments sont hachables. # Utiliser uniquement la bibliothèque standard de Python.
Python
Pourquoi trier kwargs lors de la construction de la clé du cache de mémoïsation?
Faut-il utiliser OrderedDict au lieu d'un dict normal pour un cache de mémoïsation sans limite de taille et sans politique d'expulsion?
Quelles sont les limitations et problèmes du cache en mémoire, en particulier lors de la mise à l'échelle des microservices sur plusieurs workers?
# Écrire le code pour la fonction cache. C'est un décorateur qui doit # se souvenir de ce que la fonction décorée a renvoyé, et retourner la valeur mémorisée # lors d'un appel ultérieur avec les mêmes arguments. # On peut supposer que tous les arguments sont hashables. # Utiliser uniquement la bibliothèque standard de Python. def cache(backend=None): if backend is None: backend = {} def decorator(func): def wrapper(*args, **kwargs): key = (args, tuple(sorted(kwargs.items()))) result = backend.get(key) if result is not None: return result result = func(*args, **kwargs) backend[key] = result return result return wrapper return decorator calls = {"count": 0} backend = {} @cache(backend=backend) def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert len(backend) == 1 print("OK")
# Écrire du code pour la fonction cache. C'est un décorateur qui doit # se souvenir de ce que la fonction décorée a renvoyé, et renvoyer la valeur mémorisée # lors d'un appel ultérieur avec les mêmes arguments. # # On peut supposer que tous les arguments sont hashables. # Utiliser uniquement la bibliothèque standard de Python. def cache(func): raise NotImplementedError calls = {"count": 0} @cache def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert add(2, 3) == 5 assert calls["count"] == 2 print("OK")
# Écrire le code pour la fonction cache. C'est un décorateur qui doit # se souvenir de ce que la fonction décorée a renvoyé, et retourner la valeur mémorisée # lors d'un appel ultérieur avec les mêmes arguments. # # On peut supposer que tous les arguments sont hachables. # Utiliser uniquement la bibliothèque standard de Python.
Comment éviter les collisions de cache entre différentes fonctions appelées avec les mêmes arguments, par exemple add(2, 3) et multiply(2, 3) ?
# # On peut considérer que tous les arguments sont hashables. # Utiliser uniquement la bibliothèque standard de Python. _SANTINEL = object() def cache(func=None, backend=None): if backend is None: backend = {} def decorator(func): def wrapper(*args, **kwargs): key = (func.__qualname__, args, tuple(sorted(kwargs.items()))) result = backend.get(key, _SANTINEL) if result is _SANTINEL: return result result = func(*args, **kwargs) backend[key] = result return result return wrapper if func is None: return decorator return decorator(func) calls = {"count": 0} backend = {} @cache def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert len(backend) == 1 print("OK")
# On peut considérer que tous les arguments sont hashables. # Utilisez uniquement la bibliothèque standard de Python. _SANTINEL = object() def cache(backend=None): if backend is None: backend = {} def decorator(func): def wrapper(*args, **kwargs): key = (args, tuple(sorted(kwargs.items()))) result = backend.get(key, _SANTINEL) if result is _SANTINEL: return result result = func(*args, **kwargs) backend[key] = result return result return wrapper return decorator calls = {"count": 0} backend = {} @cache(backend=backend) def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert len(backend) == 1 print("OK")