Skip to content

Instantly share code, notes, and snippets.

@eikevons
Created August 19, 2020 15:27
Show Gist options
  • Select an option

  • Save eikevons/76ce1cc3f3976be62f58d567a3aecc44 to your computer and use it in GitHub Desktop.

Select an option

Save eikevons/76ce1cc3f3976be62f58d567a3aecc44 to your computer and use it in GitHub Desktop.
Simple memoizing DAG in Python using decorators
from functools import wraps
from inspect import getmembers, ismethod
class MemoizingDAG:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# memory of target results
self._built_targets = {}
# map target names to methods
self._target_actors = {}
for name, obj in getmembers(self):
if (name.startswith('__') and name.endswith('__')
or not ismethod(obj)
or not hasattr(obj, 'target_name')):
continue
self._target_actors[getattr(obj, 'target_name')] = obj
@staticmethod
def register(name, *prerequisites):
def wrapper(f):
@wraps(f)
def f_(self, *args, **kwargs):
for req in prerequisites:
self._target_actors[req](*args, **kwargs)
# Return memoized result
if name and name in self._built_targets:
return self._built_targets[name]
result = f(self, *args, **kwargs)
# Memoize result
if name:
self._built_targets[name] = result
return result
# Dress method with target_name property
f_.target_name = name
return f_
return wrapper
class Example(MemoizingDAG):
def __init__(self):
super().__init__()
@MemoizingDAG.register('A')
def mk_A(self):
print('making A')
return 'A'
@MemoizingDAG.register('B', 'A')
def mk_B(self):
print('making B')
return 'B'
@MemoizingDAG.register('C', 'A', 'B')
def mk_C(self):
print('making C')
return 'C'
if __name__ == '__main__':
print('Example 1')
e1 = Example()
print('mk_A')
e1.mk_A()
print('mk_B')
e1.mk_B()
print('mk_C')
e1.mk_C()
print()
e2 = Example()
print('Example 2')
print('mk_C')
e2.mk_C()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment