Я использовал следующий memoizing decorator (из большой книги Python Algorithms: Освоение основных алгоритмов на языке Python... люблю его, кстати).
def memo(func):
cache = {}
@ wraps(func)
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
Проблема с этим декоратором заключается в том, что кеш-словарь на основе слова означает, что все мои аргументы должны быть хешируемыми.
Есть ли у кого-нибудь реализация (или настройка к ней), которая допускает несанкционированные аргументы (например, словари)?
Я знаю, что отсутствие хэш-значения означает, что вопрос "это в кеше?" становится нетривиальным, но я просто подумал, что попрошу.
=== ИЗМЕНИТЬ СООБЩЕНИЕ ===
Я работаю над функцией, которая возвращает стиль Parnas "использует иерархию", учитывая словарь модулей: зависимости. Здесь настройка:
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
Итак, чтобы:
>>> 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 - это функция, которую я хочу memoize, чтобы сделать эту настройку более масштабируемой. Как реализовано без memoization, он вычисляет уровень зависимостей несколько раз (например, "a" вычисляется 8 раз, как я думаю в примере выше).
Спасибо,
Mike