He estado usando el siguiente decorador de memoria (del gran libro Algoritmos de Python: Dominio de Algoritmos Básicos en el Lenguaje Python ... me encanta, por cierto).Python: ¿alguien tiene un decorador de memorando que pueda manejar argumentos irresolubles?
def memo(func):
cache = {}
@ wraps(func)
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
El problema con esto es que el decorador de diccionario basado en caché significa que todos mis argumentos deben ser hashable.
¿Alguien tiene una implementación (o una modificación de esta) que permite argumentos irresolubles (por ejemplo, diccionarios)?
Sé que la falta de un valor hash significa que la pregunta "¿está esto en el caché?" se vuelve no trivial, pero solo pensé en preguntar.
=== editado para dar un contexto ===
estoy trabajando en una función que devuelve un estilo de Parnas "utiliza la jerarquía" dado un diccionario de módulo: dependencias. Aquí está la configuración:
def uses_hierarchy(requirements):
"""
uses_hierarchy(requirements)
Arguments:
requirements - a dictionary of the form {mod: list of dependencies, }
Return value:
A dictionary of the form {level: list of mods, ...}
Assumptions:
- No cyclical requirements (e.g. if a requires b, b cannot require a).
- Any dependency not listed as a mod assumed to be level 0.
"""
levels = dict([(mod, _level(mod, requirements))
for mod in requirements.iterkeys()])
reversed = dict([(value, []) for value in levels.itervalues()])
for k, v in levels.iteritems():
reversed[v].append(k)
return reversed
def _level(mod, requirements):
if not requirements.has_key(mod):
return 0
dependencies = requirements[mod]
if not dependencies:
return 0
else:
return max([_level(dependency, requirements)
for dependency in dependencies]) + 1
Así que:
>>> requirements = {'a': [],
... 'b': [],
... 'c': ['a'],
... 'd': ['a','b'],
... 'e': ['c','d'],
... 'f': ['e']
... }
>>> uses_hierarchy(requirements)
{0: ['a', 'b'], 1: ['c', 'd'], 2: ['e'], 3: ['f']}
_level es la función Quiero memoize para hacer esta configuración más escalable. Como se implementó sin memoria, calcula el nivel de dependencias varias veces (por ejemplo, 'a' se calcula 8 veces, creo que en el ejemplo anterior).
Gracias,
Mike
Bueno, simplemente guárdelos en una lista como tuplas de '(args, result)', y repítalo. Como dices, sin embargo, no será rápido. –
@Thomas K: Un caché que se vuelve más lento cuanto más elementos tiene, suena realmente contraproducente. –
@ THC4k: Depende de lo que desee. Si va a alcanzar las mismas pocas posibilidades muchas veces, y la función es un gran cálculo o una solicitud de red lenta, podría ser más que suficiente. Y en una computadora moderna, puede ser bastante grande antes de que sea un problema. –