PyMyth: Global variables are evil... WRONG!

Rick Johnson rantingrickjohnson at
Sat Nov 16 05:01:46 CET 2013

On Friday, November 15, 2013 2:19:01 AM UTC-6, Steven D'Aprano wrote:

> But with software, coupling is *easy*. By default, code in
> a single process is completely coupled. Think of a chunk
> of machine code running in a single piece of memory. We
> have to build in our own conventions for decoupling code:
> subroutines, local variables, objects, modular code, and
> so forth. Physical objects are inherently decoupled. Code
> is inherently coupled, and we need conventions to decouple
> it. One of those conventions is to prefer local variables
> to global variables, and another is to limit the scope of
> global variables to per module rather than process-wide.

You're thoughts on "coupling" and "decoupling"
of design architecture is correct, but you only argue for
your side :-). Allow me to now argue for my side now.

And i want to leave the "safe" world of general analogies
and enter the dark esoteric word of flawed software design.

And since people only want to give me credit when i talk
about Tkinter, well then, what better example of bad design
is there than Tkinter? Hmm, well there's IDLE but that will
have to wait for another thread.

Let's see... Tkinter's design today is a single module
containing a staggering:
    155,626 chars
    3,733 lines
    30 classes 
    16 functions
    4 "puesdo-constants" (Python does not support true
    10 "module level" variables (3 of which are mutated from
    nested scopes within the module itself)
    Unwise use of a global import for the types module, even
    though only a few names are used -- AND there are
    better ways to test type nowadays!
    Unwisely auto-imports 82 Tkinter constants.
Only OpenGL is more promiscuous than Tkinter!  

But let's stay on subject shall we!

  The Road To Recovery:

The very first thing a wise programmer would do is create a
package called "tkinter". Then, he would export all class
source code to individual sub-modules -- each module being
the class name in lowercase.

Even after only a simple half hour of restructuring, the
code is starting to become maintainable -- IMAGINE THAT!



Just as the programmer thought "all was well" in "toon
town", he quickly realizes that since Python has no
intelligent global variable access, and his sub-modules need
to share data with the main tkinter module (and vise versa),
he will be forced to write:

    from tkinter import var1, var2, ..., varN
    IN EVERY DAMN SUBMODULE that needs to access or
    mutate one of the shared variables or shared

Can anyone tell me why sharing globals between sub-packages
is really so bad that we have to import things over and

And if so, would you like to offer a cleaner solution for
the problem? 

And don't give me the messy import thing, because that's 
not elegant!

Because when i see code that accesses a variable like this:

    var = value
I have no way of knowing whether the mutation is happening
to a local variable, a module level variable, or even a true
global level variable (one which extends beyond the
containing module).

Sure, i could search the file looking for imports or
global declarations, but why not use "self documenting
paths" to global variables?

The best solution is to create a global namespace. You could
name it "G". So when i see a mutation like this:

    G.var = value:
I will know that the mutation is happening to a REAL global
variable. But, even that information is lacking. I need
more... What i really want to see is this:

    G.tkinter.var = value
Boom baby! Every thing i need to know is contained within
that single line without "import everywhere".

   I am accessing a global variable
   I am accessing a global variable for the tkinter package
   The variable's name is "var"
It's explicit, but it's not SO explicit that it becomes
excessive, no. I would much rather type just a FEW more
characters than scour source code looking for obscure clues
like global declarations, imports, or whatever foolish
design you can pull out of your arse!

    And what about the mysterious "run-time injected
    global", how the heck are you planning to handle
    that one with imports?

I just want to access globals in an logical and consistent
manner via a clean interface which will alleviate all the
backtracking and detective work that causes us to lose focus
on the main architecture of our software.



Is that really too much to ask? 

Must i create a hack ( and for every missing or
broken feature in this damn language?

More information about the Python-list mailing list