Newbie: How to touch "global" variables

John Hunter jdhunter at ace.bsd.uchicago.edu
Tue Jul 30 09:59:17 EDT 2002


>>>>> "Jeff" == Jeff Layton <jeffrey.b.layton at lmco.com> writes:


    Jeff> If you have a few moments, could you help me understand
    Jeff> this a bit better and apply it to what I need?  The basic
    Jeff> concept is I need some kind of "container" class that holds
    Jeff> variables that are defined in the code (the variables will
    Jeff> not be known a priori). I would then pass that class to a
    Jeff> function in a module that would perform some operations
    Jeff> based on the variables, but not necessarily change the
    Jeff> variables (I may change my mind on that at a later date).
    Jeff> So, I would need a class that would allow me to "add"
    Jeff> variables do it and store all of the information about it's
    Jeff> state (I assume using Alex Martelli's Borg Class). I could
    Jeff> then pass the instance of the class to other functions on
    Jeff> other modules for their use.  Does this make sense?


Hi Jeff

In the future, please respond to the group.  That way other people can
contribute to and learn from the dialog.  Don't be shy -- everybody
was a newbie once.

There are 2 good ways to do what you want.  A simple class (not borg)
or a borg.  Which one you choose depends on your application and data.
Think about your container class -- should all your classes and
functions see the same data and do you want changes made in one place
to be reflected everywhere?  Are you sure there is only one unique
instance of that container?  If so it's a borg, if not a class.

Example: Suppose you had a class City.  That class might contain a lot
of data -- a list of residents, an integer specifying a zip, a string
specifying the name of the city, etc...  You could pass around
instances of that class c1 = City('New York') to a function, which
might call c1.add_resident('Bill').  By passing instances of c1
around, other functions, classes and code could access and/or change
the data in c1.  But City is not a Borg, because you might want to
make a second city c2 = City('Chicago'), which would function
independently of c1.

On the other hand, if you made a class Chicago, that would be a Borg,
because there is only one Chicago.  In the case above c1 and c2, are
instances of the class City and are different and can hold different
information.  Changes made to c1 are not seen in c2.  If Chicago is a
Borg, all instances will be the same.  So if you say c1 = Chicago()
and c2 = Chicago() and c1.add_resident('Bill') then c2 will know about
Bill.

Below is some example code, using Name as a regular class and MyShared
as a Borg.  There are 3 files: the main code, a file containing some
functions and a module MyShared containing the Borg.  A Borg should be
placed into a module so other modules can load it.  

This example was made just to show the effects of modifying and
accessing instances of classes and borgs from code that may live in a
different module.  In real life, you want to be careful about
modifying instances in functions.  If you do, make sure the functions
are clearly named, like add_resident.

John Hunter

-- begin main_borg.py ---

# this is the main level code

from MyShared import MyShared
from somefuncs import func1, func2

# A plain old class
class Name:
    def __init__(self, first, last):
        self.first = 'John'
        self.last = 'Hunter'
    def __str__(self):
        return '%s %s' % (self.first, self.last)

m = MyShared()

n1 = Name('John', 'Hunter')
n2 = Name('Joe', 'Bloggs')
print n1

func1(n1)         # adds a middle initial
print n1.middle   # changes made in func1 are preserved at the main level 
#print n2.middle  # this is an error; n2 doesn't have a middle initial

func1(n2)
print n2.middle  # this is ok now

# MyShared is a borg, so changes made in func2 are accessible in
# the main level, and vice versa.  We don't have to pass m to the
# function
func2()
print 'main: ', m.y

m3 = MyShared()       # create a new instance of MyShared
print 'main: ', m3.y  # still the same....

-- end main_borg.py ---

--- begin MyShared.py ---
# You want all everyone to be able to see this class and all instances
# should be identical

class MyShared:
    __shared_state = {}
    y = ['A', 'list', 'of', 'strings']    
    def __init__(self):
        self.__dict__ = self.__shared_state  # this is the heart of the borg
        # double underscore is private; can only be accessed through
        # get and set
        self.__x = 1  
    def get(self):
        return self.__x
    def set(self, x):
        self.__x = x

--- end MyShared.py ---

--- begin somefuncs.py ---

from MyShared import MyShared

def func1(n):
    print 'func1: the first name is %s' % n.first
    n.middle = 'D.'  # I can add a middle initial and the main level
                     # will see it.

def func2():
    # m2 this is the same as m in the main code
    m2 = MyShared()  
    m2.y.append('func2 was here')
    print 'func2: ', m2.y

--- begin somefuncs.py ---





More information about the Python-list mailing list