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

2006-04-21 Thread Ron Britton
Alan

Thanks for the thorough reply.

> 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.

It seems like a tree to me.

> 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.

This structure evolved.  As I solved one problem, I ran into another, 
and eventually ended up with the current design.  I know it's not 
ideal, but it's the result of my spotty knowledge of Python and what I 
was able to locate in the assorted documentation that I have skimmed 
through looking for things that looked relevant.

> 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 was hoping to eventually put all of the data in a separate Python 
module.  That way if it ever changed, I could just edit that file.

> 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 some point in the future?

I'm not talking to a SQL database or anything like that.  I just have 
this chunk of data.  It will change occasionally, so I need a 
convenient place to edit the data

> If it stays as 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(...),...]),...
>  ])
> ]

That looks similar to something I did before and had to abandon.  I 
suspect my earlier attempt was flawed in some way.  The above might 
work.

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

Dictionaries are only pairs of data.  I assume a list can be one of 
those elements, but I couldn't figure out how to make it work in the 
structure I presented.

> However if the data varies at runtime and you have to read it
> from an external source that approach won't work.

It doesn't.

> Why not a dictionary of modules keyed by module name?

I wanted to make the methods flexible enough that I wouldn't have to 
edit every method if the module list ever changed.  I guess I don't 
understand how a dictionary works in this situation.

> Why not write constructors that take a list as a parameter.
> The constructor can manage its own list and the higher
> level constructor just passes in the appropriate list. That way
> each class only needs to know about the data at the level
> 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 originally had tuples, but you can't access individual elements.  
E.g., give me the second item in each tuple.  I see you're using a 
dictionary in the above structure.  Maybe that solves that issue.  I'll 
have to give the above a try and see if it works.

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

That doesn't work.  It tells me "Database instance has no attribute 
'getattr'".

> but I think its easier and clearer in this case to use:
>
> db.Modules[shortmod]

If Modules is a class name, how am I able to call it like that?  I 
plugged that into my program, and it said:

"AttributeError: Database instance has no attribute 'Modules'"

> I think you can make it a much 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

IDD
(it definitely does!)

I have to run off to work now.  I'll try your suggestions when I get 
there.  Thanks a whole lot!!

Ron

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


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

2006-04-20 Thread Ron Britton
>> I wanted to make the methods flexible enough that I wouldn't have to 
>> edit every method if the module list ever changed.  I guess I don't 
>> understand how a dictionary works in this situation.
>
> I don;t understand what you don;t understand here. Can you expand on 
> why you don't think a dictionary would work?

This remark was based on one of my earlier designs.  It didn't work 
there, so I abandoned dictionaries.  The library reference says:
"Only values containing lists, dictionaries or other mutable types 
(that are compared by value rather than by object identity) may not be 
used as keys."
This added to the problem, at least in the design I attempted it in.

>> I originally had tuples, but you can't access individual elements.
>
> What makes you think so?
>
 t = (1,2,3)
 print t[0]
> 1

I didn't work before when I used it as an index.  Now it does.  I must 
have done something different originally.  But you are right.  This 
works:
 >>> mylist = ['one', 'two', 'three']
 >>> t = (0,1,2)
 >>> print mylist[t[0]]
one

 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)
>> That doesn't work.  It tells me "Database instance has no attribute 
>> 'getattr'".
>
> Its actually a special method so needs the underscores __getattr__
> and accessed via a function. I got my syntax muddled:
>
> getattr(db, shortmod)
>
> is how it should be written.

That works!  I knew there had to be a way!

Thanks for the help!
Ron

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


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

2006-04-20 Thread Alan Gauld
> Dictionaries are only pairs of data.  I assume a list can be one of 
> those elements, but I couldn't figure out how to make it work in the 
> structure I presented.

Yes, the object that is stored can be anything. Thus

>>> numList = [1,2,3]
>>> chrList = ['1','2','3']
>>> numDict = {}
>>> numDict['asNum'] = numList
>>> numDict['asChr'] = chrList
>>> for item in numDict['asNum']: print item,
...
1 2 3
>>>

shows two lists being stored in a dictionary.
You can also store instances of classes or functions 
or even the classes themselves!

> I wanted to make the methods flexible enough that I wouldn't have to 
> edit every method if the module list ever changed.  I guess I don't 
> understand how a dictionary works in this situation.

I don;t understand what you don;t understand here. Can you 
expand on why you don't think a dictionary would work?

>> Why not write constructors that take a list as a parameter.
>> The constructor can manage its own list and the higher
>> level constructor just passes in the appropriate list. That way
>> each class only needs to know about the data at the level
>> 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 originally had tuples, but you can't access individual elements.  

What makes you think so?

>>> t = (1,2,3)
>>> print t[0]
1
>>>

The only thing you can't do is alter the data in the tuple - which is 
exactly the behaviour you want if reading the tuple from a config file!

>>> 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)
> 
> That doesn't work.  It tells me "Database instance has no attribute 
> 'getattr'".

Its actually a special method so needs the underscores __getattr__
and accessed via a function. I got my syntax muddled:

getattr(db, shortmod)

is how it should be written.

>> but I think its easier and clearer in this case to use:
>>
>> db.Modules[shortmod]
> 
> If Modules is a class name, how am I able to call it like that?  

Modules is a dictionary of Modules in the db object. I 
should probably have used the example from my Module 
class above:

myModule.components[compname]

> "AttributeError: Database instance has no attribute 'Modules'"

You will need to modify the definition of the database class 
to have the Modules dictionary first! :-)

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


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


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

2006-04-20 Thread Kent Johnson
Ron Britton wrote:
> Short version:  How do I use an iterator to refer to an object's  
> attribute?  E.g., "z" is a list of attributes of  "b":
> for x, y in z:
>  for a in b.x.y

getattr(b, 'foo') is the same as b.foo. getattr takes a string for the
name of the attribute. So you would need
getattr(getattr(b, x), y)
> 
> Also, any suggestions for my overall structure below?

For once I agree with Alan on a design question :-)

You can define a useful structure directly in your configuration. It
could be nested lists and dictionaries or nested class instances,
whichever works better for the application. I think I would use nested
class instances. This is one of Python's great strengths - that you can
easily declare complex data structures in code.

PS I suggest you call your data structure something other than 
'database' since that word has a fairly specific meaning.

Kent


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


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

2006-04-20 Thread Alan Gauld
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', '