Postpone creation of attributes until needed

Giles Brown giles_brown at hotmail.com
Mon Jun 11 07:46:48 EDT 2007


On 11 Jun, 11:10, Frank Millman <f... at chagford.com> wrote:
> On Jun 11, 11:47 am, Phil Thompson <p... at riverbankcomputing.co.uk>
> wrote:
>
>
>
> > On Monday 11 June 2007 10:24 am, Frank Millman wrote:
>
> > > Hi all
>
> > > I have a small problem. I have come up with a solution, but I don't
> > > know if it is a) safe, and b) optimal.
>
> > > I have a class with a number of attributes, but for various reasons I
> > > cannot assign values to all the attributes at __init__ time, as the
> > > values depend on attributes of other linked classes which may not have
> > > been created yet. I can be sure that by the time any values are
> > > requested, all the other classes have been created, so it is then
> > > possible to compute the missing values.
>
> > Properties...
>
> >     @property
> >     def z(self):
> >         return self.x * self.y
>
> In my simple example I showed only one missing attribute - 'z'. In
> real life I have a number of them, so I would have to set up a
> separate property definition for each of them.
>
> With my approach, __getattr__ is called if *any* of the missing
> attributes are referenced, which seems easier and requires less
> maintenance if I add additional attributes.
>
> Another point - the property definition is called every time the
> attribute is referenced, whereas __getattr__ is only called if the
> attribute does not exist in the class __dict__, and this only happens
> once. Therefore I think my approach should be slightly quicker.
>
> Frank

You could treat the property access like a __getattr__ and use it
to trigger the assignment of instance variables.  This would mean that
all future access would pick up the instance variables.  Following a
kind
"class variable access causes instance variable creation" pattern
(anyone
know a better name for that?).

You may want to construct a little mechanism that sets up these
properties
(a loop, a list of attribute names, and a setattr on the class?).

If you've got to allow access from multiple threads and aren't happy
that
the calculations being idempotent is going to be sufficient (e.g. if
the calculations are really expensive) then you need some kind of
threading
lock in your (one and only?) lazy loading function.

Ok.  Enough lunchtime diversion (I should get some fresh air).

Giles




More information about the Python-list mailing list