Postpone creation of attributes until needed

George Sakkis george.sakkis at gmail.com
Mon Jun 11 11:22:58 EDT 2007


On Jun 11, 10:37 am, Frank Millman <f... at chagford.com> wrote:
> On Jun 11, 3:38 pm, George Sakkis <george.sak... at gmail.com> wrote:
> >The boilerplate code can be minimal too with an appropriate
> > decorator, something like:
>
> > class A(object):
>
> >     def __init__(self,x,y):
> >         self.x = x
> >         self.y = y
>
> >     @cachedproperty
> >     def z(self):
> >         return self.x * self.y
>
> > where cachedproperty is
>
> > def cachedproperty(func):
> >     name = '__' + func.__name__
> >     def wrapper(self):
> >         try: return getattr(self, name)
> >         except AttributeError: # raised only the first time
> >             value = func(self)
> >             setattr(self, name, value)
> >             return value
> >     return property(wrapper)
>
> This is very neat, George. I will have to read it a few more times
> before I understand it properly - I still have not fully grasped
> decorators, as I have not yet had a need for them.

You never *need* decorators, in the sense it's just syntax sugar for
things you might do without them, but they're handy once you get your
head around them.

> Actually I did spend a bit of time trying to understand it before
> posting, and I have a question.
>
> It seems that this is now a 'read-only' attribute, whose value is
> computed by the function the first time, and after that cannot be
> changed. It would probably suffice for my needs, but how easy would it
> be to convert it to read/write?

It's straightforward, just define a setter wrapper and pass it in the
property along with the getter:

def cachedproperty(func):
    name = '__' + func.__name__
    def getter(self):
        try: return getattr(self, name)
        except AttributeError: # raised only the first time
            value = func(self)
            setattr(self, name, value)
            return value
    def setter(self, value):
        setattr(self, name, value)
    return property(getter,setter)


HTH,

George




More information about the Python-list mailing list