Postpone creation of attributes until needed

Frank Millman frank at chagford.com
Mon Jun 11 10:37:06 EDT 2007


On Jun 11, 3:38 pm, George Sakkis <george.sak... at gmail.com> wrote:
> On Jun 11, 8:27 am, Frank Millman <f... at chagford.com> wrote:
>
>
> > Sorry - I made it more explicit above. It is the method that sets up
> > all the missing attributes. No matter which attribute is referenced
> > first, 'compute' sets up all of them, so they are all available for
> > any future reference.
>
> > To be honest, it feels neater than setting up a property for each
> > attribute.
>
> I don't see why this all-or-nothing approach is neater; what if you
> have a hundred expensive computed attributes but you just need one ?
> Unless you know this never happens in your specific situation because
> all missing attributes are tightly coupled, properties are a better
> way to go.

It so happens that this is my specific situation. I can have a foreign
key column in one table with a reference to a primary key column in
another table. I have for some time now had the ability to set up a
pseudo-column in the first table with a reference to an alternate key
column in the second table, and this requires various attributes to be
set up. I have recently extended this concept where the first table
can have a pseudo-column pointing to a column in the second table,
which is in turn a pseudo-column pointing to a column in a third
table. This can chain indefinitely provided that the end of the chain
is a real column in the final table.

My problem is that, when I create the first pseudo-column, the target
column, also pseudo, does not exist yet. I cannot call it recursively
due to various other complications. Therefore my solution was to wait
until I need it. Then the first one makes a reference to the second
one, which in turn realises that in needs a reference to the third
one, and so on. So it is recursive, but at execution-time, not at
instantiation-time.

Hope this makes sense.

>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.

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?

Thanks

Frank




More information about the Python-list mailing list