Do You Use the "Global" Statement in Python

In Python what is a global statement?

Every "variable" in python is limited to a certain scope. The scope of a python "file" is the module-scope. Consider the following:

#file test.py
myvariable = 5 # myvariable has module-level scope

def func():
x = 3 # x has "local" or function level scope.

Objects with local scope die as soon as the function exits and can never be retrieved (unless you return them), but within a function, you can access variables in the module level scope (or any containing scope):

myvariable = 5
def func():
print(myvariable) # prints 5

def func2():
x = 3
def func3():
print(x) # will print 3 because it picks it up from `func2`'s scope

func3()

However, you can't use assignment on that reference and expect that it will be propagated to an outer scope:

myvariable = 5
def func():
myvariable = 6 # creates a new "local" variable.
# Doesn't affect the global version
print(myvariable) # prints 6

func()
print(myvariable) # prints 5

Now, we're finally to global. The global keyword is the way that you tell python that a particular variable in your function is defined at the global (module-level) scope.

myvariable = 5
def func():
global myvariable
myvariable = 6 # changes `myvariable` at the global scope
print(myvariable) # prints 6

func()
print(myvariable) # prints 6 now because we were able
# to modify the reference in the function

In other words, you can change the value of myvariable in the module-scope from within func if you use the global keyword.


As an aside, scopes can be nested arbitrarily deeply:

def func1():
x = 3
def func2():
print("x=",x,"func2")
y = 4
def func3():
nonlocal x # try it with nonlocal commented out as well. See the difference.
print("x=",x,"func3")
print("y=",y,"func3")
z = 5
print("z=",z,"func3")
x = 10

func3()

func2()
print("x=",x,"func1")

func1()

Now in this case, none of the variables are declared at the global scope, and in python2, there is no (easy/clean) way to change the value of x in the scope of func1 from within func3. That's why the nonlocal keyword was introduced in python3.x . nonlocal is an extension of global that allows you to modify a variable that you picked up from another scope in whatever scope it was pulled from.

When is the global statement necessary?

By default, an assignment to a name always operates on a local variable, creating a new one if it is not currently defined.

The global statement makes the name refer to a variable in the global scope, permitting you to assign to a global name without creating a new local variable.

(The nonlocal statement does something similar, except it makes the name refer to a variable defined in the closest enclosing scope, which is not necessarily the global scope.)

In your first example, you are not assigning to a name; you are performing attribute lookup on a free variable, which resolves to the global variable of the same name.

In your second example, you try to create a new local variable. Since scope is determined at compile time, a = a + [1] will fail, because the a on the right-hand side will still refer to the as-of-yet undefined local variable a. With global, the assignment does not create a local variable, so the right-hand side is an expression involving the global variable, and the result is assigned to the global name as well.

Python global keyword vs. Pylint W0603

Generalized use of global variables can make maintenance a nightmare, because they make tracing the flow of your program, and sometimes you get weird bug, because some module has read the variable and acted on its value before some other module changed the value of the variable (and this can result from inverting two import statements in some unrelated 3rd module). See also the wikipedia entry on Global variables.

This is why you should avoid mutable global variables, IMO, and why Pylint issues a warning (and probably should issue more of them. Detecting the use of the global keyword is just an easy way of spotting some of them).

Don't take me wrong: I am not saying you must not use global variables. Only that you should avoid using them. There are lots of legit cases for global variables in Python. As long as you don't get more than a couple W0603, you should fare OK.

Now, Logilab (the company maintaining Pylint, and where I used to work) once had to take over maintenance of a piece of > 50kloc of Python code, with heavy duplication and 100+ mutable global variables. And this was hell.

Solutions to work around global variables include:

  • adding a parameter to the functions which need to access the variable
  • using class attributes
  • using instance attributes (by passing the value you need to the constructor of the class)
  • centralizing mutable global values in a Configuration object which is build so that it is instantiated once at program startup (using environment variables, command line, configuration file...) and never mutated after this.

Using global variables in a function

You can use a global variable within other functions by declaring it as global within each function that assigns a value to it:

globvar = 0

def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1

def print_globvar():
print(globvar) # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar() # Prints 1

Since it's unclear whether globvar = 1 is creating a local variable or changing a global variable, Python defaults to creating a local variable, and makes you explicitly choose the other behavior with the global keyword.

See other answers if you want to share a global variable across modules.

When do I need to use the global keyword in python

When you do things to foo and foo_foo, you're not changing the reference:

foo = {}
foo['key'] = 'stuff'

foo still refers to the same object as before; it just now contains more data.

bar = ['key', 'value']

This reassigns bar to refer to a new object (the list with two elements).

However, when that line is encountered inside a function, it creates a local reference bar unless you say global bar. In effect, you have two different variables named bar: the global and the local.

Saying global bar tells Python to use the global version of bar rather than creating a new local variable with the same name.

Generally, if you are modifying global variables, you should state global varname for each one to avoid accidentally creating a local.

Or, you can use a class:

class State(object):
def __init__(self):
self.foo = {}
self.foo_foo = {}
self.bar = None

state = State()

def fn():
state.bar = ['key', 'value']

The rule of thumb as to when we should use a global variable in a function

Style rules are not language rules. I.e. you shouldn't use eval(), but there it is, in the language.

tell me the rule of thumb as to when we should global a variable in a
function, and when it is not necessary?

The rules for when, and when not, to use global are simple, but even tutorials on the web get it wrong.

  1. The global keyword should not be used to create a global
    variable.

(Yes, that's partly a style rule.) When you define a top level variable outside a function, Python makes it global. (You don't use the global keyword for this.) When you assign to a variable inside a function, Python assumes it is local to the function. You only need the global keyword when you want change that later assumption so you can reassign (=) a global variable from within a function. You don't need the global declaration to examine a global variable. You don't need it to invoke a method on a global variable that might change its internal state or content:


  1. You only need the global keyword when you want to reassign (=) a
    global variable within a function.

The global declaration is used in any function where a global variable is reassigned. It is is placed ahead of the first reference to the variable, access or assignment. For simplicity, and style, global statements are put at the beginning of the function.

A statement like, "You should never use global variables", is a style rule and true of most programming languages -- apply it if/when you can. And if you absolutely can't, don't feel bad about it, just:


  1. Comment all globals you do use properly.

Global constants are less an issue:


  1. If global constants are truly constant, they never need the global
    keyword.

@juanpa.arrivillaga's example of go_left() taking the additional values as parameters instead of global variables, fails to take into account that go_left() is a callback and that the turtle event assignment functions don't provide for additional parameters. (They should, but they don't.) We can get around this using a lambda expression (or partial function from functools), but when used this way, lambda isn't particularly great style either, IMHO.

@martineau's suggestion of "making them attributes of a class that the class' methods can access" (aka class variables) is fine, but what is left unsaid is that it means subclassing Turtle or wrapping a turtle instance with another class.

My personal issue with mutable globals is that they are problematic in a multi-threaded world.

Why isn't the 'global' keyword needed to access a global variable?

The keyword global is only useful to change or create global variables in a local context, although creating global variables is seldom considered a good solution.

def bob():
me = "locally defined" # Defined only in local context
print(me)

bob()
print(me) # Asking for a global variable

The above will give you:

locally defined
Traceback (most recent call last):
File "file.py", line 9, in <module>
print(me)
NameError: name 'me' is not defined

While if you use the global statement, the variable will become available "outside" the scope of the function, effectively becoming a global variable.

def bob():
global me
me = "locally defined" # Defined locally but declared as global
print(me)

bob()
print(me) # Asking for a global variable

So the above code will give you:

locally defined
locally defined

In addition, due to the nature of python, you could also use global to declare functions, classes or other objects in a local context. Although I would advise against it since it causes nightmares if something goes wrong or needs debugging.



Related Topics



Leave a reply



Submit