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