Python Lazy Object Reloader
I’m sure there’s a more general title for this kind of object, but the challenge came up and here’s what I put together. The basic idea is to have a python class that only recomputes something hard when one of the attributes is modified. It doesn’t make sense to recompute on every modification, nor does it make sense to recompute if it’s never read.
In all cases, here’s the code sample. I’m sure it’ll be useful on stackoverflow someday.
1#
2# Decorator that takes a list of members that are cached
3#
4def second_cache(members=None) :
5 def inner(cls) :
6 cls._second_cache_dirty = False
7
8 if members is None :
9 def setter(self, name, value) :
10 if name not in ('_second_cache_dirty', ) :
11 self._second_cache_dirty = True
12 return object.__setattr__(self, name, value)
13 else :
14 cls._second_cache_members = set(members)
15 def setter(self, name, value) :
16 if name in cls._second_cache_members and name not in ('_second_cache_dirty',):
17 self._second_cache_dirty = True
18 return object.__setattr__(self, name, value)
19
20 cls.__setattr__ = setter
21
22 return cls
23 return inner
24
25#
26# A revised property decorator that checkes the cacheable state of an object and
27# calls refresh if defined and needed
28#
29def cache_prop(func) :
30 def call_me(self) :
31 if self._second_cache_dirty :
32 if hasattr(self, '_refresh') :
33 self._refresh()
34 self._second_cache_dirty = False
35 return func(self)
36 return property(call_me)
37
38#
39# Test class to demonstrate that only if the member bar is modified that the object
40# calls the refresh method.
41#
42@second_cache(members=['bar'])
43class Test(object) :
44 def __init__(self) :
45 self.bar = 1
46 self.cat = 2
47 self.dog = 3
48 self.baz = 4
49
50 def _refresh(self) :
51 print "Cache Dirty - need to refresh object"
52
53 @cache_prop
54 def frog(self) :
55 return self.bar + self.cat
56
57 def fun(self) :
58 print "BigTop"
59
60t1 = Test()
61
62print "Dirty:", t1.frog
63t1.bar = 7
64print "Dirty:", t1.frog
65print "Clean:", t1.frog