Code Snippets en

From Python
Revision as of 00:35, 28 August 2009 by AmitAronovitch (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Code Snippets (English)

Here you can put short examples of code for community review. If you have some idea or tip which seems useful, but you are not too sure and/or wish to get comments from the community before running off to publish in Python Cookbook, just click Edit, and write it up here.

Or, if you prefer to write it up in hebrew, use the hebrew snippets page.

(To keep things in order, I recommend duplicating the template at the bottom)

cprops: Cached properties using non-data descriptors

I've been using the following decorator/descriptor for some time now, and it has become a frequent pattern in my code. However, I never found the time to document it. I'll start here with the basic idea, which is quite simple, and add the extensions (don't worry, only 2-3) later if/when I find the time.

The idea of a cached-property seems to be quite known. One common use case is when your class has an attribute which takes some effort to calculate, and is not necessarily always used by applications. In such cases you wish to build it in a "lazy" way. The first time it is accessed, some specialized method is called to calculate it, but any later reference to the attribute will return the stored value.

It seems that people usually implement this using the standard "property" descriptor (sometimes even using specialized decorators). However, these implementations seemed a bit convoluted to me, due to the fact that "property" is a data descriptor. This means that the __get__ method takes precedence over the owner instance's __dict__, so one has to explicitly take care of providing the cached value on later references. On the other hand, had we used a non-data descriptor this would be taken care of automatically by the standard attribute access mechanism - all you have to do is set the attribute on the owner instance.

So, let us start with the "vanilla cprop":

class cprop(object):
    def __init__(self, func):
        self.func = func
    
    def __get__(self, obj, klass):
        val = self.func(obj)
        setattr(obj, self.func.__name__, val)
        return val

class Demo(object):
    @cprop
    def the_answer(self):
        print "calculating..."
        return 42

>>> demo = Demo()
>>> demo.the_answer
calculating...
42
>>> demo.the_answer
42

comments

  • Your response here please...

wiki template/example - please dup and edit

what it does

#put code here
# each line should start with blank
import this

Originator's comments and questions

public comments/responses

  • Write response here
Personal tools