==================== instance decorators ==================== Originally from Whit Morriss' memojito package, they are used to memoize return values for methods on an instance. The memoized values are stored on an attribute on the instance and disappear when the instance is destroyed or a cleanup is called. Let's try it out w/ a dummy class:: >>> from plone.memoize import instance >>> class MyMsg(object): ... bang='!' ... ... @property ... @instance.memoize ... def txt2(self): ... #extreme intense calculation ... return '%s world' %self.txt1 ... ... @instance.memoize ... def getMsg(self, to, **instruction): ... lst = ['%s--%s' %t for t in instruction.items()] ... instxt = ' '.join(lst) ... return ("%s: %s%s %s" %(to, self.txt2, self.bang, instxt)).strip() ... ... @instance.memoizedproperty ... def recurse(self): ... return "recursive: %s" % self.txt2 ... ... @instance.clearbefore ... def clearbefore(self): ... return self.txt2 ... ... @instance.clearafter ... def clearafter(self): ... return self.txt2 ... ... def __init__(self, txt1): ... self.txt1 = txt1 >>> msg = MyMsg('hello') >>> msg.txt2 'hello world' >>> msg.txt1 = 'nice to visit this' Even though we've twiddled txt1, txt2 is not recalculated:: >>> msg.txt2 'hello world' The memo is stored by a key made of the method's name, args, and a frozenset of any kwargs. If those are expected to be big, you should compute your own hash of it. >>> key = ('txt2', (msg,), frozenset([])) >>> msg._memojito_[key] 'hello world' The clear after decorator will clear the memos after returning the methods value:: >>> msg.clearafter() 'hello world' So now the message should have changed:: >>> msg.txt2 'nice to visit this world' We change the text again:: >>> msg.txt1 = 'goodbye cruel' The message is still the same of course:: >>> msg.txt2 'nice to visit this world' Now we can test the clear before, which does the opposite from the clear after, allowing new values to be calculated:: >>> msg.clearbefore() 'goodbye cruel world' memojito supports memoization of multiple signatures as long as all signature values are hashable:: >>> print msg.getMsg('Ernest') Ernest: goodbye cruel world! >>> print msg.getMsg('J.D.', **{'raise':'roofbeams'}) J.D.: goodbye cruel world! raise--roofbeams We can alter data underneath, but nothing changes:: >>> msg.txt1 = 'sound and fury' >>> print msg.getMsg('J.D.', **{'raise':'roofbeams'}) J.D.: goodbye cruel world! raise--roofbeams >>> print msg.getMsg('Ernest') Ernest: goodbye cruel world! If we alter the signature, our msg is recalculated, but since mst.txt2 is a memo, only the values passed in change:: >>> ins = {'tale':'told by idiot', 'signify':'nothing'} >>> print msg.getMsg('Bill F.', **ins) Bill F.: goodbye cruel world! tale--told by idiot signify--nothing >>> print msg.getMsg('J.D.', **{'catcher':'rye'}) J.D.: goodbye cruel world! catcher--rye If change the bang, the memo remains the same:: >>> msg.bang='#!' >>> print msg.getMsg('J.D.', **{'catcher':'rye'}) J.D.: goodbye cruel world! catcher--rye >>> print msg.getMsg('Ernest') Ernest: goodbye cruel world! clearing works the same as for properties:: >>> print msg.clearafter() goodbye cruel world Our shebang appears:: >>> print msg.getMsg('Ernest') Ernest: sound and fury world#! Our message to faulkner now is semantically correct:: >>> ins = dict(tale='told by idiot', signify='nothing') >>> print msg.getMsg('Bill F.', **ins) Bill F.: sound and fury world#! tale--told by idiot signify--nothing Let's make sure that memoized properties which call OTHER memoized properties do the right thing:: >>> msg = MyMsg('hello') >>> print msg.recurse recursive: hello world Now we make sure that both the txt2 and the recurse values are in the cache:: >>> print len(msg._memojito_.keys()) 2