Newbie again: computing attributes on the fly

Gordon McMillan gmcm at hypernet.com
Wed Jun 16 12:25:58 EDT 1999


Olaf Delgado writes:
> 
> here's another couple of questions to the enlightened ones. I'd like
> to compute certain properties of a class instance only once and
> store it for future use. I'd like to do those computations on demand
> only, because some might be really, really expensive. My first try
> looks like this:
> 
> class x:
>     def __getattr__(self, attr):
>         import string
>         if string.find(attr, "get_") != 0:
>             val = ( lambda x = getattr(self, "get_"+attr)(): x )
>             self.__dict__[attr] = val return val
>         else:
>             raise AttributeError("no such attribute")
> 
>     def get_lost(self):
>  return 0 # really, really expensive :)
> 
>     def get_a_life(self):
>  return 1
> 
> >>> y = x()
> >>> y.lost()
> 0
> >>> y.a_life()
> 1
> 
> Here, the lambda is pointless somehow, but hints to a potential
> desire to add parameter support in the future (which I think I don't
> need, but who knows?).
> 
> Question(s):
> 1) Is this 'good', or at least 'okay' style?
> 2) Any immediate suggestions for improvement?
> 3) Has anyone ever bothered to implement a more elegant or more
> complete
>    approach, which might, for example, include such things as
>    parameters, adding memorization to existing classes, you name it?

You're making things too complicated. __getattr__ is only called if 
the attribute is not found. So something like this will suffice:

>>> class X:
...   def __getattr__(self, nm):
...     if nm == 'foo':
...       self.foo = 17.0 * 33.1 + .01
...       return self.foo
...     raise AttributeError("no attribute %s" % nm)
...
>>> x = X()
>>> dir(x)
[]			#no instance attributes
>>> x.foo
562.71
>>> dir(x)
['foo']		#now foo is an instance attribute

If you want to generalize that, I'd see if we have an attribute 
"calc_%s" % nm and use that method (vs the inline computation).

- Gordon




More information about the Python-list mailing list