[Tutor] Fixing Globals
Dave Angel
davea at davea.name
Sat Mar 16 20:52:07 CET 2013
On 03/16/2013 03:04 PM, kendy at kendy.org wrote:
> Dear Tutor
>
> Global constants and variables are bad.
First, let me define my own "rule." Global constants should be all
uppercase, and global variables should be avoided. Trivial and buggy
scripts may ignore both rules. A trivial script is typically anything
under 30 lines. Buggy scripts are those which you delete as soon as you
ran them once.
So what's a global constant? It's something that's set once, soon after
the script starts, and *usually* not changed later in the run. For
example, cmdline arguments and things directly derived from them.
Special numbers (such as math.pi which is global in that module, and
should have been capitalized). OS-specific details.
> But what's better? I've heard some
> suggestions, but haven't seen much actual code showing how to improve globals. I
> don't like:
>
> * Passing a lot of individual arguments.
I don't know how many you consider 'a lot.' Consider factoring the
function into simpler components.
> * Creating a structure with unrelated elements.
Presumably you mean a class instance with unrelated attributes. And
yes, certainly if you're creating a singleton class just as a holder for
a pile of globals, then you might as well use the globals() collection
in a given module. rather than writing your own. On the other hand,
things that are unrelated in one context may very well be related in
another. Smart dividing up of the problem is one of the things that
helps makes code readable and reusable.
> * Passing a structure, as an argument, through a function that uses only one (or
> none of the) elements in the structure.
Here, I have to disagree entirely. If the class is intelligently
designed, the instance is holding a bunch of interconnected data. If
the function needs one thing from it, no harm done passing the whole
instance.
An example is a gui 'listbox' instance. It has lots of data that the
gui will use in painting it, positioning it, and generating events about
it. But an individual portion of the code may be only interested in the
selected item in the list, not in the title, nor the horizontal size,
nor ...
>
> I created an example (below), that could be written with global constants and
> variables. How would you suggest handling something like this? (I don't need you
> to stick to my example.)
>
> #!/usr/bin/python
>
> START = '<'
> END = '>'
>
> def getargs():
> getops()
> if
> in_filename_1 =
> in_filename_2 =
> out_filename_1 =
> out_filename_2 =
> flag1 =
> verbose =
Take a look at the modules in the standard library that do this sort of
thing. They return an object which contains all the parsed parameters.
>
> def this():
> open_for_read()
> stuff()
And if you decide to open two files instead of one, and process them
both in a similar way? Suddenly you'll need to pass a filename into
this function. Why not start that way, so the function is readable?
>
> def open_for_read(filename):
> in_filehandle = open(
> return in_filehandle
Looks good.
>
> def stuff():
def stuff(c, foo):
""" interpret the character c and set the flag that will control
how the rest of the program works
"""
> if c == START or c == END:
> foo_the_bar =
if c in START+END:
foo.BAR =
>
> def that():
> things()
> write_status(out_filename_1)
Why are these in one function, if they're unrelated?
The rest of the examples were too abstracted to be able to comment on.
>
> def things():
> bar_the_foo = foo_the_bar
> if verbose:
> print(flag1)
>
> def write_status(out_filename_1):
>
> getargs()
> this()
> that()
>
>
> I very much appreciate the help that you have given me!
>
> Thanks
> Ken
>
When you start writing code that's big enough to have reusable pieces,
you'll begin to appreciate how writing parameterized code makes it more
reusable. And when you try to debug stuff where a change in one
function's use of a global breaks another function far away, you'll
start to appreciate how it's handy to have each function have a
(somewhat) reduced space it can damage, or be damaged by.
My biggest disasters were "trivial" programs that grew beyond their
original scope, and I never changed the mindset in rewriting them. I
had once such program recently which had many authors and was a real
mess. (Besides, it was written in perl, which it makes it much easier
to write unmaintainable hacks) I wanted to make a substantial change
and wound up writing a new program that invoked the first. That first
couldn't walk on my globals once it was in a separate process.
--
DaveA
More information about the Tutor
mailing list