On Jun 11, 8:27 am, Frank Millman <[EMAIL PROTECTED]> wrote: > On Jun 11, 1:56 pm, Steven D'Aprano > > <[EMAIL PROTECTED]> wrote: > > > Unless you have thousands and thousands of instances, __slots__ is almost > > certainly not the answer. __slots__ is an optimization to minimize the > > size of each instance. The fact that it prevents the creation of new > > attributes is a side-effect. > > Understood - I am getting there slowly. > > I now have the following - > > >>> class A(object): > > ... def __init__(self,x,y): > ... self.x = x > ... self.y = y > ... def __getattr__(self,name): > ... print 'getattr',name > ... self.compute() > ... return self.__dict__[name] > ... def compute(self): # compute all missing attributes > ... self.__dict__['z'] = self.x * self.y > [there could be many of these] > > >>> a = A(3,4) > >>> a.x > 3 > >>> a.y > 4 > >>> a.z > > getattr z > 12>>> a.z > 12 > >>> a.q > > KeyError: 'q' > > The only problem with this is that it raises KeyError instead of the > expected AttributeError. > > > > > You haven't told us what the 'compute' method is. > > > Or if you have, I missed it. > > 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. 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) HTH, George -- http://mail.python.org/mailman/listinfo/python-list