2

The answer should be 2 because first the main() function is called, then the first() function is called, overriding the global variable num = 0 which was defined outside of any functions, therefore rendering it a variable with global scope. Yet I get the following error:

UnboundLocalError: local variable 'num' referenced before assignment  

Why am I getting this error?

def first():
    num = num + 1

def main():
    num = 1
    first()
    print(num)

num = 0

num_result = main()

print(num_result) 
Dr.Doom2020
  • 43
  • 1
  • 3
  • 8

5 Answers5

10

The OP wrote (emphasis mine):

The answer should be 2 because first the main() function is called, then the first() function is called, overriding the global variable.

It is not overriding the global variable. Unless you explicitly specify a variable as global, if there is any assignment to the variable in a function, it is assumed to be local. See also the python tutorial on defining functions where it states (emphasis mine):

More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.

and the documentation of the global statement (if anyone using Python 3 is looking at this, please also take a look at the (compared to global) very useful nonlocal statement and its PEP 3104).

To "fix" your code:

def first():
    global num
    num = num + 1

def main():
    global num
    num = 1
    first()
    print(num)

num = 0

num_result = main()

print(num_result) 

Do not use global variables in this way please. @LutzHorn has shown in his answer how to do it right.

The reason to avoid global variables is that their effect is hard to test for, and as soon as code gets complex enough, hard to reason about. If every function modifies global variables instead of properly taking parameters and returning values, understanding what the code actually does is hard as soon as one has more than a week or so of distance from it.

Jonas Schäfer
  • 20,140
  • 5
  • 55
  • 69
  • 1
    If you look at the code, num = 0 was defined outside of any functions. Should it not have a global scope then? – Dr.Doom2020 Jun 06 '16 at 07:56
  • @Dr.Doom2020 No. In which scope a variable is looked up solely depends on the function body. "In case of doubt", local variables take precedence, and local scope is the default for any name you assign to. Please read and try to understand the part of the tutorial I linked. Come back if you have further questions. :-) – Jonas Schäfer Jun 06 '16 at 08:11
  • The variable num is global, which means it can be accessed and changed in all of the functions in the script. So num is changed in main() and in first() – Dr.Doom2020 Jun 06 '16 at 08:32
  • No, it can not be changed unless you *declare* it `global` inside the function. –  Jun 06 '16 at 09:37
  • 1
    In a nice universe, yes your common sense understanding is how it should work. Imo this global bs is the only drawback of python, a simple little thing in a simple little irrelevant script can become an absolute nightmare. – NOP da CALL Jul 09 '17 at 21:18
  • @NOPdaCALL I don’t understand your feedback, can you clarify please? – Jonas Schäfer Jul 10 '17 at 08:14
7

Inside first, num is not known. Use arguments and return statements.

def first(num):
    return num + 1

def main():
    num = 1
    num = first(num)
    return num

num = 0

num_result = main()

print(num_result)
  • 3
    Should it not be known though? Because num = 0 was defined with a global scope, so why is it not defined inside of first() function? – Dr.Doom2020 Jun 06 '16 at 07:54
  • No, `num` was not defined with global scope. Please don't put the same comment under each answer. Try to understand scope in Python. –  Jun 06 '16 at 09:18
  • 5
    What do you call the num variable outside of the functions, if that is not global, what is it? – Dr.Doom2020 Jun 06 '16 at 09:23
  • 1
    But this does not mean that it is available for assignment inside a function. If you want to do `num = ...`, you must declare `global num` inside `first`. But using globals is considerd bad style. –  Jun 06 '16 at 09:36
0

This is a scope error. In first, there is no num before you try to add one to it. You can call a variable in a bloc if it is declared in this bloc, in an upper bloc or if it is declared global.

To pass variables, you can use arguments of the function:

def first(num):
    return num + 1

def main():
    shmilblik = first(1)
    print(shmilblik)
Paul
  • 315
  • 1
  • 9
0

"num" is not defined in the function "first". It is not a global variable, it is out of the scope of "first". To make it global just edit your function like this:

def first():
    global num
    num = num + 1

Using globals is bad practice in my opinion. you could achieve the same by using parameters and a return like this:

def first(num):
    return num + 1

def main(num):
    num = 1
    num = first(num)
    print(num)
    return num

num = 0

num_result = main(num)

print(num_result) 
Matthias Schreiber
  • 2,347
  • 1
  • 13
  • 20
0

The variable num is just initialized in the main-method, you're not initializing it in the first()-Method. So you've to hand it over to the first()-Method.

def first(num):
    return num + 1

def main():
    num = 1
    num = first(num)
    return num

num = 0

num_result = main()

print(num_result)