one-time initialization of class members

Steven Bethard steven.bethard at gmail.com
Wed Jun 13 23:42:36 EDT 2007


James Turk wrote:
> It actually occured to me that I could use a @classmethod to do the
> loading and take that out of the BaseClass constructor.  What I have
> makes more sense and eliminates the unecessary constructors.
> 
> ie.
> 
> class BaseClass:
>     @classmethod
>     def loadData(params):
>         #expensive load here
> 
> class ChildClass1(BaseClass):
>      dataset = BaseClass.loadData(params)
> 
> This is pretty much along the lines of what you suggested, thank you
> for the hint in the right direction.
> 
> I realized that this still doesn't meet my needs exactly as I only
> want the expensive dataset to be loaded if/when a class is actually
> used (there are potentially many of these and only a few will be
> used).

Seems like you want a lazy class attribute. How about something like::

 >>> class LazyClassAttribute(object):
...     def __init__(self, func):
...         self.func = func
...     def __get__(self, obj, cls=None):
...         value = self.func(cls)
...         setattr(cls, self.func.__name__, value)
...         return value
...
 >>> class Base(object):
...     @LazyClassAttribute
...     def dataset(cls):
...         print 'calculating dataset'
...         return 'dataset(%s)' % cls.params
...
 >>> class Child1(Base):
...     params = 'foo'
...
 >>> class Child2(Base):
...     params = 'bar'
...
 >>> Child1.dataset
calculating dataset
'dataset(foo)'
 >>> Child1.dataset
'dataset(foo)'
 >>> Child2.dataset
calculating dataset
'dataset(bar)'
 >>> Child2.dataset
'dataset(bar)'

The idea is basically similar to the @classmethod approach except that 
instead of @classmethod, we use a custom descriptor that calls the 
method the first time it's accessed and then stores that value 
afterwards. This means that instead of explicitly calling the 
@classmethod, the method will be called whenever the attribute is first 
accessed.

STeVe



More information about the Python-list mailing list