Using a class as a structure/container

david.car7 at gmail.com david.car7 at gmail.com
Wed Feb 6 19:50:49 EST 2008


On Feb 6, 2:18 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar> wrote:
> En Wed, 06 Feb 2008 00:59:48 -0200, <david.c... at gmail.com> escribi�:
>
>
>
> > Is it appropriate to use a class as a simple container in order to
> > access attributes using a series of dot operators?  Is their a more
> > Pythonic way of doing this?  For instance, I have a "container" class
> > which is never instantiated directly, but only through another class.
> > Access to certain attributes would be something like:
>
> >   main_class.a.b.x
>
> > where row and v1 are instances of the container class which are
> > instantianted by main_class.  I know I can use dictionaries, but this
> > syntax is a little clearer as long as the number of dot operators is
> > not too lengthy.  Some code would be something like:
>
> > class container(object):
> >     def __init__(self):
> >         pass
>
> You can omit the __init__ method if it's empty
>
> > class main_class(object):
> >     def __init__(self):
> >         self.a = container()
> >         settatr(self.a, 'b', container())
> >         settatr(self.a.b, 'x', 2)
>
> Usually written as:
>          self.a.b = container()
>          self.a.b.x = 2
>
> Nothing in the language forbids doing what you do, but I'd ask if the  
> attributes may be split logically between the various containers, or it is  
> an artificial division and they really should be attributes of the  
> main_class.
> There are documentation problems too: such generic container cannot tell  
> which attributes are valid or not; introspection tools cannot tell very  
> much about the class; perhaps some code completion tools get confused. I  
> don't like a long sequence of dots either.
> Using such a deep structure you are violating the Law of Demeter "Don't  
> talk to strangers"http://en.wikipedia.org/wiki/Law_of_Demeter(altough I  
> don't follow it strictly, things like xobj.parent.connection.user.name  
> look wrong to me)
>
> Another problem of such generic container is that you don't get any  
> meaningful information when printing it. You may find the NamedTuples  
> recipe useful; look into the Python Cookbook  http://www.activestate.com/ASPN/Python/Cookbook/- or perhaps using this  
> class:
>
> class Record(object):
>      def __init__(self, **kw):
>          self.__dict__.update(kw)
>
>      def __repr__(self):
>          values = ['%s=%r' % item
>                    for item in sorted(self.__dict__.iteritems())]
>          return '%s(%s)' % (self.__class__.__name__, ','.join(values))
>
>      __str__ = __repr__
>
> x = Record(a=1, b=2.0, c="three")
> print x
> # output: Record(a=1,b=2.0,c='three')
>
> --
> Gabriel Genellina

Hi Gabriel,

Thanks for the information.  The reason why I was taking this approach
was more from a user interface perspective.  What I have is a file
that contains certain geometric objects, lets call them geo.  Each geo
object has 4 possible surfaces: ps, ss, le, te.  Each surface has
x,y,z coordinates.  It is not known apriori if any of these surfaces
exist in the file.  So I created a geo_reader class that is passed a
filename in its argument list.  It then parses the file, creating a
container class for each geo object and assigning the name geo0, geo1,
geo2, etc... as an attribute of the geo_reader class.  The geo_reader
class also stores global attributes concerning the file, i.e. the
number of geo objects, etc...  Then for each geo container I bind
another container class for each surface that I find for each geo
object, i.e. the ps, ss, le, te surfaces.  Then the coordinates for
each of the surfaces becomes an attribute of each of their
corresponding containers.  The user then can access the data as such:

my_geo = geo_reader("thefilename")

# get the number of geo objects in the file
print my_geo.number_of_objects

# get the number of surfaces for the geo0 object
print my_geo.geo0.number_of_surfaces

# get the x-coordinates for the ps surface of the geo0 object
if has_attr(my_geo.geo0, 'ps', False): x_coords = my_geo.geo0.ps.x

I can also bind certain attributes to the container class to tell
whether its a geo object or surface, etc.  I just didn't want the user
to have to use the dictionary syntax like this:

x_coords = my_geo['geo0']['ps']['x']

It just seems a little more natural to use the dot operator approach
for users to interface with.  I wasn't aware of the Law of Demeter and
I agree with all your concerns.  I'm just not sure which one a user
would rather interface with from the command line.  The dot operators
are quicker to type.

Thanks for hyperlinks.  Great reading.  All the best

-------
David Car



More information about the Python-list mailing list