Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #55512 > unrolled thread

Re: Class or Dictionary?

Started byJean-Michel Pichavant <jeanmichel@sequans.com>
First post2011-02-11 21:01 +0100
Last post2011-02-12 01:06 -0800
Articles 5 — 2 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Class or Dictionary? Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-02-11 21:01 +0100
    Re: Class or Dictionary? Martin De Kauwe <mdekauwe@gmail.com> - 2011-02-11 15:45 -0800
      Re: Class or Dictionary? Martin De Kauwe <mdekauwe@gmail.com> - 2011-02-12 01:20 -0800
      Re: Class or Dictionary? Martin De Kauwe <mdekauwe@gmail.com> - 2011-02-11 16:24 -0800
      Re: Class or Dictionary? Martin De Kauwe <mdekauwe@gmail.com> - 2011-02-12 01:06 -0800

#55512 — Re: Class or Dictionary?

FromJean-Michel Pichavant <jeanmichel@sequans.com>
Date2011-02-11 21:01 +0100
SubjectRe: Class or Dictionary?
Message-ID<mailman.114.1297454525.1633.python-list@python.org>
Martin De Kauwe wrote:
> Hi,
>
> I have a series of parameter values which i need to pass throughout my
> code (>100), in C I would use a structure for example. However in
> python it is not clear to me if it would be better to use a dictionary
> or build a class object? Personally I think accessing the values is
> neater (visually) with an object rather than a dictionary, e.g.
>
> x = params['price_of_cats'] * params['price_of_elephants']
>
> vs.
>
> x = params.price_of_cats * params.price_of_elephants
>
> So currently I am building a series of class objects to hold different
> parameters and then passing these through my code, e.g.
>
> class EmptyObject:
>     pass
>
> self.animal_prices = EmptyObject()
> self.price_of_cats = 12 or reading a file and populating the object
>
>
> I would be keen to hear any reasons why this is a bad approach (if it
> is, I haven't managed to work this out)? Or perhaps there is a better
> one?
>
> thanks
>
> Martin
>   
Using classes is the best choice.

However, if because there would be too much classes to define so that 
you are forced to use your EmptyObject trick, adding attributes to the 
inntance dynamically, I'd say that dictionnaries are a more common pattern.

Ideally, you would have something like:

class PriceHolder(object):
    @classmethod
    def fromFile(cls, filename):
       # example of abstract method
       pass

class Animals(PriceHolder):
    def __init__(self):
       self.cat = None
       self.elephant = None

class Fruits(PriceHolder):
    def __init__(self):
       self.banana = None
       self.apple = None


Then you would have to write 100 PriceHolder subclasses...

JM

[toc] | [next] | [standalone]


#55659

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2011-02-11 15:45 -0800
Message-ID<3d711f8b-8651-4add-84a6-c66a0a1dd64a@o32g2000prb.googlegroups.com>
In reply to#55512
Hi,

yes I read a .INI file using ConfigParser, just similar sections (in
my opinion) to make one object which i can then pass to different
classes. E.G.

class Dict2Obj:
    """ Turn a dictionary into an object.

    The only purpose of this is that I think it is neater to reference
values
    x.soiltemp rather than x['soiltemp'] ;P
    """
    def __init__(self, dict):

        for k, v in dict.items():
            setattr(self, k, v)


class Parser(object):
    """ Load up all the initialisation data.

    Return the met data as an array, perhaps we should really also
return a
    header as well? Return the ini file as various objects.

    """
    def __init__(self, ini_fname, met_fname):

        self.ini_fname = ini_fname
        self.met_fname = met_fname

    def load_files(self):

        # read the driving data in, this may get more complicated?
        met_data = met_data = np.loadtxt(self.met_fname, comments='#')

        # read the configuration file into a different dicts, break up
        # into model_params, control and state
        config = ConfigParser.RawConfigParser()
        config.read(self.ini_fname)

        # params
        model_params = {}
        sections =
['water','nitra','soilp','carba','litter','envir','prodn']
        for section in sections:
            for option in config.options(section):
                model_params[option] = config.getfloat(section,
option)

        # turn dict into an object
        model_params = Dict2Obj(model_params)

        # control
        control = {}
        for option in config.options('control'):
            control[option] = config.getint('control', option)

        # turn dict into an object
        control = Dict2Obj(control)

        initial_state = {}
        sections = ['cinit','ninit','vinit']
        for section in sections:
            for option in config.options(section):
                initial_state[option] = config.getfloat(section,
option)

        # turn dict into objects
        initial_state = Dict2Obj(initial_state)

        return (initial_state, control, model_params,
met_data)

So I would then pass these objects through my code, for example a
given class would just expect to inherit params perhaps.

class calc_weight(object):

    def __init__(self, params):
        self.params = params

There are also "states" that evolve through the code which various
methods of a given class change. For example lets call it elephants
weight. So the model will do various things to predict changes in our
elephants weight, so there will be a class to calculate his/her food
intake etc. Using this example the other thing I wanted to do was pass
"states" around like self.elephant_weight. However it occurred to me
if I just used self.elephant_weight for example it would make it
harder to call individual components seperately, so better to stick to
the same method and using an object i reasoned. Hence I started with
my emptydict thing, I hope that helps make it clearer?

class EmptyObject:
    pass


# generate some objects to store pools and fluxes...
self.pools = EmptyObject()

# add stuff to it
self.pools.elephant_weight = 12.0

thanks for all of the suggestions it is very insightful

[toc] | [prev] | [next] | [standalone]


#55689

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2011-02-12 01:20 -0800
Message-ID<c3149d45-d042-4322-8107-26a28475ac4d@q40g2000prh.googlegroups.com>
In reply to#55659
On Feb 12, 8:06 pm, Martin De Kauwe <mdeka...@gmail.com> wrote:
> On Feb 12, 7:21 pm, Andrea Crotti <andrea.crott...@gmail.com> wrote:
>
> > Il giorno 12/feb/2011, alle ore 00.45, Martin De Kauwe ha scritto:
>
> > > Hi,
>
> > > yes I read a .INI file using ConfigParser, just similar sections (in
> > > my opinion) to make one object which i can then pass to different
> > > classes. E.G.
>
> > Ok then I suggest configobj, less buggy and much more powerful than ConfigParser:http://www.voidspace.org.uk/python/configobj.html
>
> > (and included from python 2.7).
> > In this way you can also simply just carry around that dictionary, and it will be correctly
> > typed if you validate the input.
>
> That is interesting however I am using python 2.6 so I guess I shall
> have to stick as I am for the moment. I think the way I used it above
> was quite straight forward? It seemed OK? What are the issues?

Ignore that I have just tested it (it works in 2.6), much better!
Thanks!!

[toc] | [prev] | [next] | [standalone]


#55897

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2011-02-11 16:24 -0800
Message-ID<508804b1-fa3e-4bf1-827f-c1617c6f9750@r19g2000prm.googlegroups.com>
In reply to#55659
Sorry I should have added a little more example to help with clarity?
So after reading the .INI file I then initialise the objects I
described e.g.

 def initialise_simulation(self):
    """Set the initial conditions.

    using values from the .ini value set the C and N pools
    and other misc states.

    """
    for attr, value in self.initial_state.__dict__.iteritems():
        #print attr, value
        setattr(self.pools, attr, value)

    # maybe need M2_AS_HA here?
    self.pools.lai = self.params.sla * self.params.cfrac_dry_mass
    self.fluxes.nuptake = 0.0

[toc] | [prev] | [next] | [standalone]


#55934

FromMartin De Kauwe <mdekauwe@gmail.com>
Date2011-02-12 01:06 -0800
Message-ID<0e22259e-d1b6-4685-80ad-24a306ffd33b@k17g2000pre.googlegroups.com>
In reply to#55659
On Feb 12, 7:21 pm, Andrea Crotti <andrea.crott...@gmail.com> wrote:
> Il giorno 12/feb/2011, alle ore 00.45, Martin De Kauwe ha scritto:
>
> > Hi,
>
> > yes I read a .INI file using ConfigParser, just similar sections (in
> > my opinion) to make one object which i can then pass to different
> > classes. E.G.
>
> Ok then I suggest configobj, less buggy and much more powerful than ConfigParser:http://www.voidspace.org.uk/python/configobj.html
>
> (and included from python 2.7).
> In this way you can also simply just carry around that dictionary, and it will be correctly
> typed if you validate the input.

That is interesting however I am using python 2.6 so I guess I shall
have to stick as I am for the moment. I think the way I used it above
was quite straight forward? It seemed OK? What are the issues?

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web