Kent Johnson wrote:
On Fri, Oct 30, 2009 at 6:39 PM, Robert Lummis <robert.lum...@gmail.com> wrote:
I want to move some functions from my "main" program file to a module
file because the main file is getting too big for convenience. The
functions access arrays (lists of lists) that are defined and
initialised in the main file. How do I reference the main file arrays
from statements within the module file?

A couple of solutions:
- Put the arrays into some kind of structure that you can pass as an
argument. The structure could be a list, dict or custom class.
- Create a class (or possibly more than one class) to hold both the
data and the functions that operate on it.

With everything in the main file a function like the following works
as expected:

def functionA (row, col, x):
    grid[row][col] =a value that depends on x and other values in grid>

where grid[] is initialised outside of any functions (i.e. in the main).

So how do I write that function when I move it to a module file? I

That might make a good method of a grid class. Then it would become
something like
def functionA(self, row, col, x):
  self.grid[row][col] =..

So how do I write that function when I move it to a module file? I
thought I read somewhere that the main routine has the name "__main__"
so I tried:

 __main__.grid[row][col] =...>

 but that gives "NameError: name '__main__' is not defined".

You can
  import __main__
and the above will work but that is *not* the best solution.

I understand that it is best to minimize cross-file references but I
feel it is warranted in this case.

Cross-file references are not bad by themselves but circular
references (module A uses module B and B uses A) are a bad idea.

Even if you think it isn't good
practice I would like to understand how to do it (or else why it can't
be done). Is there some other way to keep files from getting too big?

Yes. Object-oriented design is the most common way of dealing with
this. Think about decomposing your code into cooperating objects.

Kent

Listen to everything Kent tells you. He knows more about Python than I probably ever will. But I have been programming for a long time, and sometimes I have to be pragmatic on the way to becoming correct. So take this next suggestion as a stop-gap while you debug some of these concepts.

Make a brand new module just to hold these global variables. Call it constants.py

In that module, give your initial values for all these globals, but don't do anything else. If absolutely necessary, make a single function in the module that'll be called at the very beginning of the script to do further initialization. Above all, don't put any imports in this module, except for the obvious stdlib ones, such as os and sys. But not to any other module of your own code.

Now, add an import of that module everywhere you need access to these, including from your script. So if you need access to the constant grid, you reference it with constants.grid

Now I deliberately called the module constants because good practice says you'd only use this approach for things which do not change while the program is running. Things like flags passed in from the command line, or environmental things like the directory in which files are to be stored.

So if you followed my advice to call it constants.py, then you'd be reminded each time that this is a temporary hack.

Personally, I like the class approach, where related data is grouped together, so a single parameter can be added to each function. And many times, this can lead to generalizations where you suddenly realize that instead of one grid, you need to operate on more than one, and the same functions could deal with either one. Passing grid (or a class object containing grid) would then be a fortunate choice. And realize that object-orientation isn't an all-or-nothing approach. Make objects out of those groups of things that you think there's ever going to be a chance of multiple usage, and leave the rest separate values.

And in addition to instance attributes, you can create methods, but you could start by doing just the lowest level ones. For example if your grid is implemented as a list of lists, maybe you want accessor methods that give it a different appearance, like a single vector. Or if there are two attributes that are interrelated, you can use methods to keep them in synch, instead of counting on everyone following the rules.

DaveA

_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to