Using a class as a structure/container

D

david.car7

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

class main_class(object):
def __init__(self):
self.a = container()
settatr(self.a, 'b', container())
settatr(self.a.b, 'x', 2)

Thanks in advance.
 
D

david.car7

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

class main_class(object):
    def __init__(self):
        self.a = container()
        settatr(self.a, 'b', container())
        settatr(self.a.b, 'x', 2)

Thanks in advance.

Oops. I meant "where a and b are instances..." instead of "where row
and v1 are instances..." above. Sorry for the confusion.
 
G

Gabriel Genellina

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')
 
D

david.car7

En Wed, 06 Feb 2008 00:59:48 -0200, <[email protected]> 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')

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
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
(snip)
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:

You mean it has one of the 4 surfaces, or it has them all ?
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.

You want an indexed ordered collection (ie: something like a list) here.
The geo_reader
class also stores global attributes concerning the file, i.e. the
number of geo objects,

a list handle this.
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.

Err... Why don't you actually take time to write the Geo and Surface
classes ? It will *really* save you time in the long run.
I can also bind certain attributes to the container class to tell
whether its a geo object or surface, etc.

You definitively want to write the appropriate classes.
I just didn't want the user
to have to use the dictionary syntax like this:

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

As far as I'm concerned, I'd use a list-like interface for my_geo, ie:

my_geo[0].ps.x

And I'd define the four surface attributes of the Geo object, default
them to either None or a NullSurface object (whose x and y attribs have
the None value).
It just seems a little more natural to use the dot operator approach
for users to interface with.

wrt/ attribute access, yes, indeed. wrt/ what is clearly an ordered
collection, there's already a well defined interface !-)

And anyway, this doesn't mean you should not properly define your
classes - this is no more complex than what you're doing here, and it
will make your code *way* more readable, maintainable and usable - even
for your users, since they'll be able to introspect your objects type,
print the docstrings (if you write them of course), eventually use
autocompletion (cf the rlcompleter module) etc.
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.

Indeed. Now if you have such concern, why not go all the way ?-)

My 2 cents
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top