Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global and local variables in Python

I am learning Python. A book on Python 3 says the following code should work fine:

def funky():
    print(myvar)
    myvar = 20
    print(myvar)

myvar = 10
funky()

But when I run it in Python 3.3, I got the

UnboundLocalError: local variable 'myvar' referenced before assignment

error. My understanding is that the first print(myvar) in funky should be 10 since it's a global variable. The second print(myvar) should be 20 since a local myvar is defined to be 20. What is going on here? Please help clarify.

like image 981
JACKY Li Avatar asked Oct 23 '25 11:10

JACKY Li


2 Answers

You need to call global in your function before assigning a value.

def funky():
    global myvar
    print(myvar)
    myvar = 20
    print(myvar)

myvar = 10
funky()

Note that you can print the value without calling global because you can access global variables without using global, but attempting to assign a value will require it.

like image 116
mgoffin Avatar answered Oct 26 '25 00:10

mgoffin


From the docs:

Each occurrence of a name in the program text refers to the binding of that name established in the innermost function block containing the use.

It means that unless you declare it global or nonlocal (nested functions) then myvar is a local variable or a free variable (if myvar is not defined in the function).

The book is incorrect. Within the same block the name represents the same variable (local variable myvar in your example, you can't use it until you define it even if there is a global variable with the same name). Also you can change values outside a function i.e., the text at the end of page 65 is also incorrect. The following works:

def funky(): # local
    myvar = 20 
    print(myvar) # -> 20
myvar = 10 # global and/or local (outside funky())
funky()
print(myvar) # -> 10 (note: the same)

 

def funky(): # global
    global myvar
    print(myvar) # -> 10
    myvar = 20
myvar = 10
funky() 
print(myvar) # -> 20 (note: changed)

 

def funky(): # free (global if funky is not nested inside an outer function)
    print(myvar) # -> 10
myvar = 10
funky() 

 

def outer():
    def funky():  # nonlocal
        nonlocal myvar
        print(myvar) # -> 5
        myvar = 20
    myvar = 5 # local
    funky()
    print(myvar) # -> 20 (note: changed)
outer()
like image 22
jfs Avatar answered Oct 26 '25 02:10

jfs