[Tutor] Accessing class instances [Party people]

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Thu Mar 18 00:36:48 EST 2004



On Wed, 17 Mar 2004, Steve George wrote:

> The basic idea in my program is to have a number of classes as follows:
>
> MainProgram()
> 	"" Does all my start-up stuff and controls it """
>
> Options()
> 	""" parses options and stores them as attributes"""
>
> DataLoader()
> 	""" Loads a data file and allows operations on it """
>
> I put MainProgram() and Options() classes into one single text file and
> my DataLoader() class into another.
>
> When I instantiate my DataLoader object I want it to look at the
> instance of my Options() class and pull some information from it.  At
> the moment I get:
>
> in get_price
>      print Opts.line_size
> NameError: global name 'Opts' is not defined


Hi Steve,

I think we'll need to see more code; the problem here might be as simple
as a capitalizing problem, or something more subtle.



> a.  I don't think I understand how a class can query an instance of a
> class So here my DataLoader class when it's instantiated needs to query
> an instance of my Options() class named Opts.

The DataLoader appears to need to talk to Opts.  Did you send Opts out to
the DataLoader instance?  Where is Opts defined, in the Operations module?



> At the moment I understand how one module can access another and
> instantiate an object e.g. DataLoader.dataloader() but I'm less clear
> how a module can access the instance of that class at runtime.

It's possible to access it by name, but you probably will need to put the
module name in there too.  So say that we're in DataLoader, and we want to
get at a variable called "Opts" that lives in the 'options' module.
While we're standing in DataLoader, we need to say:

    options.Opts



> b.  Have I mis-used modules?
> I used the different files/modules thinking that it logically separated
> how I was thinking about the problem.  Howerver, there is some
> information I need to pass back and forward between them, the use of
> 'options' is a good example.  How do Python programmers normally get
> around this?


When classes need to communicate with each other, it's often possible to
"matchmake" them.  Here's an example:

###
>>> class Person:
...     def __init__(self, name):
...         self.name = name
...         self.friends = []
...     def meet(self, other):
...         self.friends.append(other)
...     def greet(self):
...         for friend in self.friends:
...             print "I", self.name, "greet you,", friend.name
...
>>> a = Person("Alice")
>>> b = Person("Bob")
>>> a.meet(b)
>>> a.greet()
I Alice greet you, Bob
>>>
>>>
>>> c = Person("Cathy")
>>> a.meet(c)
>>> a.greet()
I Alice greet you, Bob
I Alice greet you, Cathy
###

Here, we're letting each Person talk to one other by letting them "meet"
each other first.  What's neat is that this approach allows us to tie
these folks together in interesting and wacky ways:

###
>>> def party(people):
...     for p in people: p.greet()
...
>>> c.meet(b)
>>> b.meet(a)
>>> party([a, b, c])
I Alice greet you, Bob
I Alice greet you, Cathy
I Bob greet you, Alice
I Cathy greet you, Bob
###


The key to this is to let each instance keep a little bit of memory of who
they've met.  In the Person class definition, we say that every Person
remembers by keeping track of their aquaintences in a 'people' list.


But if a person just needs to remember one person, we can just say:

###
>>> class SolitaryPerson:
...     def __init__(self, name):
...         self.name = name
...         self.friend = None
...     def meet(self, other):
...         self.friend = other
...     def greet(self):
...         if self.friend:
...             print "I", self.name, "greet you,", self.friend.name
...         else:
...             print "but I don't have any friends.  Waaa."
...
>>> d = SolitaryPerson("Dan")
>>> d.greet()
But I Dan don't have any friends.  Waaa.
>>> d.meet(a)
>>> d.meet(b)
>>> d.meet(c)
>>> d.meet(d)
>>> d.greet()
I Dan greet you, Dan
###

in which case, we get a SolitaryPerson who is really close-knit.


Anyway, so no lists are really necessary.  But the idea of these instances
talking to each other, keeping tabs on each other by maintaining some
state in 'self', should be a little clearer.


This approach of getting instances aware of each other is usually
preferred over hardcoding references to other modules --- it's a little
easier to redefine the ties that bind each other with the matchmaking
approach.


Hope this helps!




More information about the Tutor mailing list