[Tutor] Use iterator to refer to an object's attribute?

Alan Gauld alan.gauld at freenet.co.uk
Thu Apr 20 10:21:39 CEST 2006


Hi Ron, I'm confused and may be missing something but it
sounds to me like a classic tree structure that you are trying
to build for each module.

> Also, any suggestions for my overall structure below?

I''m not sure why you put filling the database into a separate
function rather than as a method of the Database class, it
could then be called from the init method. This would give
it direct access to the Database attributes.

Also I don't understand why you need the componentlist
name. What is this used for? The name of the list is surely
an internal variable within the module of no relevance to
the outside world?

I'm also not clear about the database structure. Is the one
represented here the final striucture - ie a set of Python lists.
Or will you eventually be loading the data from a config file
or a relational database at somne point in the future?
If it stays at it is then the whole design seems overly
complex since you could simply load the data as part of
the object construction/instantiation process, something like this:

ModuleList = [
     Module( "Motherboard",
                   [Component("Camera",
                                        [Command(p1,p2,p3), 
Command(p4,p5)]),
                   ]),
    Module("Controller",
                   [Component("Major Controller",
                                        [Command(....),....]),
                   Component("Minor Controller",
                                        [Command(....),....]),...
                   ]),
    Module("End User",
                  [Component("xMotor", [Command(...),...]),...
                  ])
]

I suspect the use of a dictionary might be beneficial too.

However if the data varies at runtime and you have to read it
from an external source that approach won't work. OTOH
if you are iusing a relational DB then the links between the
components can be constructed as relations between the tables
so that will simplify construction. The most complex case is
where you are loading from flat files. But we need a bit more
info I think. But whichever method is used I'd put the code
into the classes and let each class load its own data.

Here's how I'm tackling it:
• I have a bunch of lists that have everything defined in them
(module_list; cpt_??_lists for components; and cmd_??_lists for
commands).

• I'm creating a database object, "db", which will hold everything.

• I iterate across the module list.  The idea here is to create within
the database one module object for each real object in the instrument,
in this case three.  I should end up with:  db.mb, db.ct, and db.eu.

Why not a dictionary of modules keyed by module name?

• There is a short name (for use by the program), a long name (which
will be displayed to the user), and the name of that module's component
list.

Why not write constructors that take a list as a parameter.
The constructor can manage its own liust and the higher
level constructor just passes in the appropriate list. That way
each class only needs to know about the data at the lebvel
it is responsible for. So the Module class might look a bit like:

class Module:
    def __init__(self, name, componentlist):
         self.components = {}
         self.name = name
         for component in componentlist:
             self.components[component[0]] = Component(component)

This implies that the component list is structured as a list of tuples.

• I also create an empty list object, which will ultimately be
populated with the contents of that module's component list.

As above I'd recommend using a dictionary rather than a list.

• Then (theoretically) for each module, I iterate across that module's
component list to create several component objects inside the module (I
will then continue this process, creating command objects within the
components.).

Yes, thats the idea but let the objects do it for themselves.

> My immediate problem is that Python doesn't let me use the iterator as 
> the name of an object's attribute.

Thats where the dictionary comes in.

> I have object "db.mb".  I have iterator "shortmod" with a value of  "mb". 
> Why can't I call "db.shortmod"?

You can use db.getattr(shortmod) but I think its easier
and clearer in this case to use:

db.Modules[shortmod]

> I'm all ears.  The reason for doing it this way is that I wanted my 
> database to be the logical equivalent of the instrument.

I think you can make it a miuch closer equivalent than you
have at present, and I think that by breaking up the fill db
function and moving responsibility into the classes that it
will be much simplified. And use dictionaries rather than lists.

HTH,

Alan G
Author of the learn to program web tutor
http://www.freenetpages.co.uk/hp/alan.gauld

#--- 
Definitions-----------------------------------------------------------
#   shortname, longname, component list name
#---Modules
module_list = [
     ['mb', 'Motherboard', 'cpt_mb_list'],
     ['ct', 'Controller', 'cpt_ct_list'],
     ['eu', 'End User', 'cpt_eu_list']]

#---Components
#   shortname, longname, command list name
# Motherboard
cpt_mb_list = [
     ['icam', 'Internal Camera', 'cmd_icam_list']]

# Controller
cpt_ct_list = [
     ['maj', 'Major Controller', 'cmd_maj_list'],
     ['min', 'Minor Controller', 'cmd_min_list']]

# End User
cpt_eu_list = [
     ['xmtr', 'X Motor', 'cmd_xmtr_list'],
     ['ymtr', 'Y Motor', 'cmd_ymtr_list'],
     ['zmtr', 'Z Motor', 'cmd_zmtr_list']]

#---Commands
# Abbreviation, string, command, param1, param2
# Motherboard Commands
cmd_icam_list = [
     ['ss', 'Shutter Speed', 'shutSpeed', 0, 0],
     ['ap', 'Aperture', 'aperture', 0, 0],
     ['exp', 'Exposure', 'exposure', 0, 0]]

# Controller Commands
cmd_maj_list = [
     ['on', 'Turn it on', 'turnON', 0, 0],
     ['off', 'Turn it off', 'turnOFF', 0, 0]]
cmd_min_list = [
     ['low', 'Set Power Low', 'setLow', 0, 0],
     ['hi', 'Set Power High', 'setHigh', 0, 0]]

# End User Commands
cmd_xmtr_list = [
     ['xpos', 'Go to X-Position', 'xPosition', 0, 0]]
cmd_ymtr_list = [
     ['ypos', 'Go to Y-Position', 'yPosition', 0, 0]]
cmd_zmtr_list = [
     ['zpos', 'Go to Z-Position', 'zPosition', 0, 0]]

#--- 
Logic-----------------------------------------------------------------
#****************My immediate problem occurs in this
object***************
def fillout_DB(filldb):
     '''Build the database of modules, components, and commands.
     Feed it an empty database, and it will fill it out.'''
     # Add modules
     for shortmod, longmod, cptlist in module_list:
         filldb.addMod([shortmod, longmod, cptlist])
         print filldb.modlist
         print 'Just loaded %r, %r, and %r' % (shortmod, longmod,
cptlist)
         # Add components
         #********************The following line
chokes********************
         for shortcpt, longcpt, cmdlist in filldb.shortmod.cptlist:
             # It doesn't get to next line.  Suspect it won't work
either.
             filldb.shortmod.addCpt([shortcpt, longcpt, cmdlist])
             print 'Just loaded %r, %r, and %r' % (shortcpt, longcpt,
cmdlist)
     print 'Finished buildModules()!!!!'
     return filldb

class Database:
     '''This is the root class.  The database contains all of the module
     objects.  Each module contains all of its component objects, etc.'''
     def __init__(self):
         self.modlist = []

     def addMod(self, mod):
         self.modlist.append(mod)

class Module:
     def __init__(self, shortname, longname, cptlistname):
         self.name = shortname
         self.longname = longname
         self.cptlistname = cptlistname
         self.cptlist = []

     def addCpt(self, cpt):
         self.cptlist.append(cpt)

class Component:
     def __init__(self, shortname, longname, cmdlistname):
         self.name = shortname
         self.longname = longname
         self.cmdlistname = cmdlistname
         self.cmdlist = []

     def addCmd(self, cmd):
         self.cmdlist.append(cmd)

class Command:
     def __init__(self, shortname, longname, actualcommand, param1,
param2):
         self.name = shortname
         self.longname = longname
         self.actcmd = actualcommand
         self.paramlist = [param1, param2]

def main():
     print "It's working so far!"
     db = Database()
     fillout_DB(db)

if __name__ == "__main__":
     main()





More information about the Tutor mailing list