Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do I need to use the global keyword in python

Tags:

python

Okay, so I've had this really annoying problem where a variable got set locally but then outside of that function reverted to it's old self (in this case None), but at the same time I could manipulate other variables and still can without using the "global" keyword.

I can't provide the real code for this but it goes something like this:

foo = {}
foo_foo = {}
bar = None


def changes_foo():
    ...do some stuff to foo...

class EditThread(threading.Thread):

    def __init__(self):
        setup()

    def run(self):
       for key, value in foo.items():
           do_update_task(key, value)

    def do_update_task(self, key, value):
         ...do some editing too foo...
         del foo[key]
         bar = [key, value]
         foo_foo[key] = value

def print_the_bar():
    print bar 

Please note that all the operations on foo and foo_foo works just fine, but bar is still None when I call print_the_bar, and I've had lots of print statements in my code to verify that bar inside of do_update_task indeed has the correct values and isn't None.

Could someone please explain to me why it is so?

like image 816
Daniel Figueroa Avatar asked Aug 08 '12 14:08

Daniel Figueroa


2 Answers

If you only need to read the value of a global variable in a function, you don't need the global keyword:

x = 3
def f():
    print x

If you ever set the value of a global variable, you need the keyword so that you don't create a local variable:

x = 3
def f():
    global x
    x = 5

f()
print x
like image 78
chepner Avatar answered Oct 13 '22 13:10

chepner


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']
like image 32
mrb Avatar answered Oct 13 '22 13:10

mrb