one-time initialization of class members

James Turk james.p.turk at gmail.com
Wed Jun 13 21:43:04 EDT 2007


On Jun 13, 9:03 pm, Steven D'Aprano
<s... at REMOVE.THIS.cybersource.com.au> wrote:
> On Wed, 13 Jun 2007 23:55:02 +0000, James Turk wrote:
> > On Jun 13, 6:54 pm, Steven Bethard <steven.beth... at gmail.com> wrote:
> >> James Turk wrote:
> >> > Hi,
>
> >> > I have a situation where I have some class members that should only be
> >> > done once.  Essentially my problem looks like this:
>
> >> > class Base(object):
> >> >     dataset = None
>
> >> >     def __init__(self, param):
> >> >         if type(self).dataset is None:
> >> >             # code to load dataset based on param, expensive
>
> >> > class ChildClass1(Base):
> >> >     def __init__(self):
> >> >         Base.__init__(self, data_params)
>
> >> > class AnotherChildClass(Base):
> >> >     def __init__(self):
> >> >         Base.__init__(self, other_data_params)
>
> >> > This seems to work, initialization is only done at the first creation
> >> > of either class.  I was just wondering if this is the 'pythonic' way
> >> > to do this as my solution does feel a bit hackish.
>
> >> What should happen with code like::
>
> >>      ChildClass1('foo')
> >>      ChildClass1('bar')
>
> >> The 'param' is different, but 'dataset' should only get set the first time?
>
> >> STeVe
>
> > ChildClass doesn't take the parameter in it's constructor, it supplies
> > it for the BaseClass.  Every ChildClass of the same type should use
> > the same dataset.
>
> Then each type of ChildClass should be a sub-class, and provide it's own
> dataset:
>
> class BaseClass:
>     dataset = None
>     # blah blah blah...
>
> class ChildClass1(BaseClass):
>     dataset = SomethingUseful
>
> class ChildClass2(BaseClass):
>     dataset = SomethingElse
>
> --
> Steven.

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).  I believe I have two options:

1) put each ChildClass in a separate file
2) in each ChildClass constructor put a check if the dataset has been
loaded yet, so that the first time an instance is created it can call
the BaseClass.loadData

for now I have chosen the second option, which is to change the child
classes to resemble

class ChildClass(BaseClass):

    dataset = None

    def __init__(self):
        if BaseClass.dataset is None:
            self(type).dataset = BaseClass.loadData(params)


I am still doing the self(type) access, but I like it more now that
I've taken it out of the BaseClass constructor.




More information about the Python-list mailing list