Sto usando il seguente decoratore di memoizing (dal grande libro Python Algorithms: Mastering Algorithms di base nel linguaggio Python ... lo adoro, btw).Python - qualcuno ha un decoratore memoizing in grado di gestire argomenti non selezionabili?
def memo(func):
cache = {}
@ wraps(func)
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
Il problema con questo decoratore è che la cache basata sul dizionario significa che tutti i miei argomenti devono essere lavabili.
Qualcuno ha un'implementazione (o un tweak su questo) che consente argomenti inaffidabili (ad es. Dizionari)?
So che la mancanza di un valore di hash significa che la domanda "è presente nella cache?" diventa non banale, ma ho pensato di chiedere.
=== A cura di fornire un contesto ===
Sto lavorando ad una funzione che restituisce uno stile di Parnas "utilizza gerarchia" dato un dizionario di modulo: dipendenze. Ecco il programma di installazione:
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
In modo che:
>>> 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 è la funzione che voglio Memoize per rendere questa configurazione più scalabile. Come implementato senza memoization, calcola il livello di dipendenze più volte (ad esempio 'a' è calcolato 8 volte penso nell'esempio sopra).
Grazie,
Mike
Bene, salvali in una lista come tuple di '(args, result)', e iterate su di esso. Come dici tu, però, non sarà veloce. –
@Thomas K: una cache che diventa più lenta più gli elementi che ha sembrano davvero controproducenti. –
@ THC4k: dipende da cosa si desidera. Se stai andando a colpire le stesse poche possibilità molte volte, e la funzione è un grosso calcolo, o una richiesta di rete lenta, potrebbe benissimo essere più che buona. E su un computer moderno, può diventare piuttosto grande prima che sia un problema. –