473,387 Members | 1,553 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

one-time initialization of class members

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.

Jun 13 '07 #1
9 1270
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
Jun 13 '07 #2
On Jun 13, 6:54 pm, Steven Bethard <steven.beth...@gmail.comwrote:
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.

Jun 14 '07 #3
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.
I could be missing something but dataset is shared among all the class
instances. If you reset it based on param it will be reset every time
you create a new instance of the Base class with a different param. Is
that really what you want to do? If so just use:

class Base(object):
dataset = None

def __init__(self, param):
if self.dataset is None:
# code to load dataset based on param, expensive
-Larry
Jun 14 '07 #4
On Jun 13, 8:00 pm, Larry Bates <larry.ba...@websafe.comwrote:
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.

I could be missing something but dataset is shared among all the class
instances. If you reset it based on param it will be reset every time
you create a new instance of the Base class with a different param. Is
that really what you want to do? If so just use:

class Base(object):
dataset = None

def __init__(self, param):
if self.dataset is None:
# code to load dataset based on param, expensive

-Larry
I'm sorry, I somehow omitted the fact that the dataset does indeed
need to vary based on the child class, actually this is the main
difference between child classes.

Jun 14 '07 #5
On Wed, 13 Jun 2007 23:55:02 +0000, James Turk wrote:
On Jun 13, 6:54 pm, Steven Bethard <steven.beth...@gmail.comwrote:
>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.

Jun 14 '07 #6
En Wed, 13 Jun 2007 22:03:50 -0300, Steven D'Aprano
<st***@REMOVE.THIS.cybersource.com.auescribió:
On Wed, 13 Jun 2007 23:55:02 +0000, James Turk wrote:
>>James Turk wrote:

I have a situation where I have some class members that should only
be
done once. Essentially my problem looks like this:
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
But the OP also stated that creating the dataset is expensive. The
original code does what you say (each ChildClass is a subclass and
provides its own dataset) so I think is an acceptable solution:

pydef build_dataset(x):
.... print "building dataset:",x
.... return [x]
....
pyclass Base(object):
.... dataset = None
.... def __init__(self, param):
.... if type(self).dataset is None:
.... type(self).dataset = build_dataset(param)
....
pyclass ChildClass1(Base):
.... def __init__(self):
.... Base.__init__(self, "Params for ChildClass1")
....
pyclass AnotherChildClass(Base):
.... def __init__(self):
.... Base.__init__(self, "Params for AnotherChildClass")
....
pyc1 = ChildClass1()
building dataset: Params for ChildClass1
pyc2 = AnotherChildClass()
building dataset: Params for AnotherChildClass
pyc3 = ChildClass1()
pyprint Base.dataset
None
pyprint ChildClass1.dataset
['Params for ChildClass1']
pyprint AnotherChildClass.dataset
['Params for AnotherChildClass']
pyprint c1.dataset
['Params for ChildClass1']
pyprint c3.dataset
['Params for ChildClass1']
pyprint c1.dataset is c3.dataset
True
py>
--
Gabriel Genellina

Jun 14 '07 #7
On Jun 13, 9:03 pm, Steven D'Aprano
<s...@REMOVE.THIS.cybersource.com.auwrote:
On Wed, 13 Jun 2007 23:55:02 +0000, James Turk wrote:
On Jun 13, 6:54 pm, Steven Bethard <steven.beth...@gmail.comwrote:
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.

Jun 14 '07 #8
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
Jun 14 '07 #9
On Jun 13, 11:42 pm, Steven Bethard <steven.beth...@gmail.comwrote:
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.

Jun 14 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
by: M. Clift | last post by:
Hi, Just a quick one. I'm trying to call with this, but I keep getting 'unhashable'. I've tried various ' " and nextName = {:,\ 'Rita':],\ 'Sue':],\ 'Mary':}
28
by: Steve Bywaters | last post by:
There are several hundred of my client's franchisees happily accessing my ASP/VBscript web site... but one - just one - has reported the following: "I have been trying to log onto the LSM since...
20
by: Felix E. Klee | last post by:
Hi, when I compile the program below with gcc -O0 -o ctest ctest.c (Platform: Intel Celeron (Coppermine), LINUX 2.4.20) I get the following output: one != one_alt one_alt != one 1. !=...
14
by: serge | last post by:
I have a scenario where two tables are in a One-to-Many relationship and I need to move the data from the Many table to the One table so that it becomes a One-to-One relationship. I need to...
7
by: rjl444 | last post by:
I created 2 tables with one to one relationship. if I add a record in table A, how does table B record get created? Does SQL do this automatically because it is one to one relationship? or do I...
7
by: Randy Yates | last post by:
I'm a complete newbie to postgres so please look the other way if these questions are really stupid. Is it legitimate to have one database per data file? For organizational and backup purposes,...
22
by: petermichaux | last post by:
Hi, I'm curious about server load and download time if I use one big javascript file or break it into several smaller ones. Which is better? (Please think of this as the first time the scripts...
2
by: Sky | last post by:
Hello: I'm trying to make sense of snk files, when to use, under what conditions to regenerate new ones,...can someone take a look if these statemes make sense? And then the final questions at the...
0
by: CatchSandeepVaid | last post by:
We all know that one-to-one associations are non-lazly fetched but during this fetching the filters are not applied. I debugged hibernate code and found that hibernate finally calls...
1
by: CatchSandeepVaid | last post by:
I have posted this question in hibernate forums also.. As this forum is related to java, i am posting it here also ... In hibernate, presently one-to-one associations are fetched non-lazily... I...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.