-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecorators.py
51 lines (40 loc) · 1.53 KB
/
decorators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from functools import wraps
def __string_args_key_gen(*args, **kwargs):
"""
Key gen function for dynamic programming.
Will create a string from args. Some issues might be seen with
deep data types if order is not consistant.
"""
key = (str(args), str(sorted(kwargs)),
str([kwargs[k] for k in sorted(kwargs)]))
return key
def dynamic_programming(*args, **kwargs):
"""
Decorator function that should be able to wrap many functions to make them
dynamic programming / memoisation.
Functions should be pure and not have external factors (such as external web calls)
as this could give incorrect results.
"""
# TODO: Check safty accross many functions using it simutainously. I belive this should be ok
# as the closure containse the _store and I have checked a simple example.
# TODO: Add other backends such as flatfile or db as options
func = None
if len(args) == 1 and callable(args[0]):
func = args[0]
key_func = kwargs.get('key_func', __string_args_key_gen)
def outer(func):
_store = {}
@wraps(func)
def inner(*args, **kwargs):
key = key_func(args, kwargs)
prev = _store.get(key)
if prev != None:
# 'returning from cache'
return prev
else:
# 'new calculation'
ret = func(*args, **kwargs)
_store[key] = ret
return ret
return inner
return outer(func) if func else outer