ethical questions about global variables

rurpy at yahoo.com rurpy at yahoo.com
Tue Dec 16 07:00:32 CET 2008


On Dec 15, 7:45 pm, "Giampaolo Rodola'" <gne... at gmail.com> wrote:
> in a module of mine (ftpserver.py) I'd want to add a (boolean) global
> variable named "use_gmt_times" to decide whether the server has to
> return times in GMT or localtime but I'm not sure if it is a good idea
> because of the "ethical" doubts I'm gonna write below.
>
> In first place I've never liked global variables too much and always
> preferred per-class-instance variables instead.

By "per-class-instance variables", you are talking
about instance attributes?  I.e. "self.use_gmt_times"?
I don't see much difference between global variables
and instance attributes.  One of the main problems
that make global variables bad is that they can be
referenced and set anywhere in a program, so it can
be very difficult, when one finds a global has a
wrong value at some point, to figure out how it got
that value.

Consider the following:

~~~ Snippet 1 ~~~
#my_module
def func1():
    global A
    A = 1
def func2
    global A
    A = 2
def func3
    global A #Yes, this is redundant
    print A

~~~ Snippet 2 ~~~
class my_class:
  def func1():
    self.A = 1
  def func2
    self.A = 2
  def func3
    print self.A

What's the difference between snippet 1 and
snippet 2?  In the snippet 1, one says "global A";
in the snippet 2, "self." -- in this case it is
just a spelling difference.  If globals are "evil"
then so must be the isomorphic use of attributes
in snippet 2.

I suppose one can say that classes are generally
smaller than modules so that the "globalish" aspect
of attributes is acceptable.  But then one must
conclude that the prohibition against using globals
also applies to using instance attributes in large
classes.  Or conversely, that globals are perfectly
acceptable, even desirable, in small modules.

Note also that the common workaround to eliminate
globals, passing them as arguments, doesn't really
change anything either:

#my_module
class Config: pass
config = Config()

def func1(state):
    config.A = 1
def func2(state)
    config.A = 2
def func3(state)
    print config.A

In other words, it is not the "global" keyword
that causes problems, it is the anti-pattern
of making a variable accessible in a read/write
manner to a large number of functions without
much control over who can change it or when.
That anti-pattern can exist with globals, with
instance attributes, or with function arguments.
Simply avoiding globals is not sufficient to avoid
the anti-pattern.

> The problem in my case is that I have to use such variable in two
> separated classes: FTPHandler and VirtualFileSystem. Also, I want that
> for no reason one class uses times in GMT and the other one local
> times.
>
> Another doubt is the naming convention. PEP-8 states that global
> variables should use the lower_case_naming_convention but I've seen a
> lot of library module using the UPPER_CASE_NAMING_CONVENTION. What am
> I supposed to do about it?

I generally use an initial capital letter for my
global variables.  I think it is useful to have
some signal that a variable may be set outside
the scope of the local function/method.



More information about the Python-list mailing list