4

I've tried looking at a few different examples, but I'm not really sure why this isn't working. Say I've some code like this:

def loadVariable():
    global count
    count = 0

def loadDictionary():
    location = 'some location'
    global myDict
    myDict = pickle.load(open(location, 'rb'))

def main():
    loadVariable()
    loadDictionary()
    for item in myDict:
        if item.startswith("rt"):
            count += 1
            item = item[3:]

if __name__ == '__main__':
    main()

To my eyes, the if statement is executed which starts the main() method. Then, the variable which is global is loaded, the dictionary is loaded and the for loop is executed.

However, when I run the code I am told that the local variable count is referenced before its assignment. Why is that happening?

Edit (Explaining some of the things I've written in comments):

This doesn't work (although I think that's because global is used wrong here):

global count

def loadVariables()
    count = 0

def main():
    loadVariables()
    rest of code etc

This doesn't work either:

def loadVariables()
    count = 0

def main():
    global count
    loadVariables()
    rest of code etc

The only way thus far I've gotten it to work is using the link provided above, which is to treat the count as a list, like so:

def loadVariables():
    global count
    count = [0]

def main():
    loadVariables():
    rest of code etc
        count[0] += 1
Andrew Martin
  • 5,619
  • 10
  • 54
  • 92
  • There's no variable called `count` anywhere. I think you're misunderstanding how `global` works. – Phillip Cloud Aug 18 '13 at 01:05
  • @PhillipCloud No, that part works fine. `loadVariable` creates a global variable `count`, and `loadDictionary` created a global variable `myDict`. –  Aug 18 '13 at 01:08

3 Answers3

4

global means that within the function containing the global declaration, the name in the global declaration refers to a global variable. It does not mean "this thing is a global variable; treat it as global everywhere." In main, the names count and myDict refer to local variables, because main does not declare that it wants to use the globals.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • So another question. If I put "global count" at the top of the main method, and then use the loadVariable() method to do: "count = 1", why does it still return the same error? – Andrew Martin Aug 18 '13 at 01:11
  • @AndrewMartin: You probably removed the `global` declaration from `loadVariable`, in which case `count = 1` assigns to a variable local to `loadVariable`. The scope of a variable is completely unaffected by what function called the current function; `global count` in `main` doesn't affect `loadVariable`. – user2357112 Aug 18 '13 at 01:13
  • So I would need to reference global in BOTH main and loadVariables? – Andrew Martin Aug 18 '13 at 01:18
  • Yes. That said, you shouldn't be using global variables for this. If you want to pass information into a function, pass it as an argument. If you want to get information out of a function, return it. – user2357112 Aug 18 '13 at 01:25
  • Thanks. That makes sense. Was messing around and just trying to learn some more. – Andrew Martin Aug 18 '13 at 01:26
2

The issue is that you're not declaring count as a global variable in the main function, so when the compiler sees that you're (eventually) assigning to it, it assumes that it's a local variable. Since it's value is read before it's assigned, you get an exception.

So, the most basic fix is just to add global count at the top of main(), but I think avoiding globals would be a better option. Why not have loadVariable and loadDictionary return their results, rather than assigning them to globals? If in main() you did count = loadVariable(), count would be a local variable, and you'd have no problems later trying to reassign it.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • The original reason was because I've simplified this example. In reality, seven or eight variables are loaded in that method. I did try to add global count to the top of the method and inside loadVariables() do count = 0, but I still get the error. – Andrew Martin Aug 18 '13 at 01:08
  • 1
    Well, then post all the code. If you do the correction suggested by @Blcknght to the one you did post, it works correctly. – Mario Rossi Aug 18 '13 at 01:13
  • @MarioRossi: Just posted it – Andrew Martin Aug 18 '13 at 01:18
  • So after reading the other answer provided, I'd need to put global count at the top of both main AND the loadVariable method? – Andrew Martin Aug 18 '13 at 01:21
  • @AndrewMartin: You need to keep the global statement in `loadVariables` too, not just move it to `main`. Each function has it's own scope, so if you're assigning to a global in more than one function, you need to use the `global` statement in each one. – Blckknght Aug 18 '13 at 01:22
  • Got it. I was treating it like static in java and wondering why it didn't apply everywhere. – Andrew Martin Aug 18 '13 at 01:22
0

Here's a simple example of how global works

global_var = 0

def updater():
    global global_var
    global_var += 1


def stuff(x):
    updater()
    return global_var + x

if __name__ == '__main__':
    stuff(2)  # returns 3
Phillip Cloud
  • 24,919
  • 11
  • 68
  • 88