Operation of Python's LRU cache
<p>I've got the following code:</p>

<pre><code>def sharpe(self):
    return (self.weighted_returns()/self.weighted_returns().std())*np.sqrt(252)
</code></pre>

<p>Where <code>self.weighted_returns()</code> has a <code>@lru_cache(maxsize=None)</code> decorator.</p>

<p>Will <code>self.weighted_returns()</code> be calculated once or twice?</p>

<p>You could use <code>functools.lru_cache</code> for this. But if you're only caching the calculations for <code>self</code> and the function does not use an argument, it is an overkill. </p>

<p>Rather, I'd steal the lazy <a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/api/decorator.html#pyramid.decorator.reify" rel="nofollow"><code>reify</code></a> decorator from Pyramid:</p>

<pre><code>class reify(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped
        update_wrapper(self, wrapped)

    def __get__(self, inst, objtype=None):
        if inst is None:
            return self
        val = self.wrapped(inst)
        setattr(inst, self.wrapped.__name__, val)
        return val
</code></pre>

<p>And use it on <code>weighted_returns</code>, turning it into a lazily calculated attribute:</p>

<pre><code>@reify
def weighted_returns(self):
    # calculate the returns using self normally
    return returns
</code></pre>

<p>Then your calculation would be </p>

<pre><code>self.weighted_returns / self.weighted_returns.std() * np.sqrt(252)
</code></pre>

<p>(notice the lack of parentheses). </p>

<p>Unlike <code>functools.lru_cache(maxsize=None)</code> which will keep a dictionary of unlimited size (it is going to increase in size until you kill the program), the <code>reify</code> decorator caches the calculation result on the instance itself. If the instance is garbage-collected, then so are its cached weighted returns. </p>

python python-3.x