Globals or objects?

Steve Holden steve at holdenweb.com
Sat Feb 23 08:16:44 EST 2008


Steven D'Aprano wrote:
> On Fri, 22 Feb 2008 18:53:54 +0000, tinnews wrote:
> 
>>>> But you're not comparing what the OP posted.  He was comparing a
>>>> global with an object with a single variable inside it.  Either would
>>>> work with the y = spam(arg) example above.
>>> What do you mean by "an object with a single variable inside it"? I
>>> don't understand what that is supposed to mean, or why you think it is
>>> the same as a global. Do you mean a Singleton?
>>>
>>> If so, then the answer is simple: using a Singleton argument instead of
>>> a global is better, because with a global you are stuck to always using
>>> the global (at least until you can re-write the code), but with the
>>> Singleton argument, you may be enlightened and *not* use a Singleton.
>>>
>> But if you stop using the Singleton the code no longer does the same as
>> it would with a global does it?
> 
> That's a *good* thing, not a problem. The whole idea is to get away from 
> the bad behaviour of globals, not find some other way to implement it.
> 
I think that advocation of a global singleton is not really solving the 
problem. Not the problem I perceive, anyway. From your comments it's 
difficult to see whether we share the same perceptions, so let me elucidate.

The issue I have with globals is primarily that use of a global 
introduces a tight coupling between a function and its environment, 
since any environment that uses the function has to provide the global.

It's true that a global singleton is a half-way step to a solution of 
the problem because it portends the true solution, which also solves the 
problem of multiple counts. That solution, of course, is to have the 
"function" become a method of some counter object, which can then be 
used to count many things.

In other words (untested, so ignore the many Holden types that this will 
inevitably incur):

--------
bad.py:

counter = 0

def count(n):
     global counter
     counter += n
--------
justasbadifnotworse.py:

class bunch: pass;

counter = bunch()
bunch.count = 0

def count(n):
     counter.count += n
--------
better.py:

class Counter:
     def __init__(self):
         self.count = 0

counter1 = Counter()
counter2 = Counter()

def count(n, counter):
     counter.count += n
--------
best.py:

class Counter:
     def __init__(self):
         self.count = 0
     def count(self, n):
         self.count += n
--------

Now the names I have chosen are pejorative, but this is typically the 
development you see in someone's programming style as they slowly (or 
not slowly) start to understand the value of the object-oriented approach.

Unfortunately this sometimes goes too far, and people end up writing 
"monster objects", with dozens of methods and lots of instance variables 
used to communicate between them. With that style of programming the 
instance variables introduce the same tight coupling between the methods 
that globals do in a less object-oriented style, and the code becomes 
just as difficult to understand. Only now there can be multiple 
instances of the badly-written function!

Sometimes this is inevitable, but good programming style is about trying 
to strike the right balance between contexts. It is truly possible to 
write good and bad programs in any language you like, and rules like 
"globals are bad" need to be taken in context just like any other rule.

After all, some things *have* to be global for our programs to make any 
sense at all, unless you want to adopt a truly functional style that has 
never appealed to me. I like my programs to have state.

regards
  Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/




More information about the Python-list mailing list