one-time initialization of class members

James Turk james.p.turk at gmail.com
Thu Jun 14 10:22:36 EDT 2007


On Jun 13, 11:42 pm, Steven Bethard <steven.beth... at gmail.com> wrote:
> 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

This is a pretty interesting idea, I hadn't thought of using a
decorator to get this behavior.  I'm evaluating it and will see if it
fits in with the rest of the system well, but it certainly is a unique
solution to this problem.




More information about the Python-list mailing list