1

I have the following modules:

main.py

import my_import

my_import.a_func()

my_import.py

FOO = "foo"
BAR = []

def a_func():
   BAR.append("bar") #ok
   FOO = FOO + "foo" #UnboundLocalError: 
                     #local variable 'FOO' referenced before assignment

This is probably due to the importing, but how?

[EDIT]

From the answers I get it is not the importing that is the crulpit, but the follwing is still weird:

FOO = "foo"
BAR = []
def a_func():
    BAR.append("bar")
    print(FOO)
a_func()

--> prints "foo"

FOO = "foo"
BAR = []
def a_func():
    BAR.append("bar")
    print(FOO)
    FOO = FOO + "foo"    
a_func()

--> fails with "UnboundLocalError: local variable 'FOO' referenced before assignment" AND DOES NOT PRINT "foo"

Looks like the interpreter is looking for assignments in the current scope before it actually runs the code.

3 Answers 3

5

When Python parses a function definition, it notes all variable names that are on the left-hand side of assignment statements, such as

FOO = FOO + "foo"

It registers all such variable names as local variables.

Let me emphasize that the assignment statement causes Python to register FOO as a local variable at the time the function definition is parsed, not when the function is called. So later, when the function is called, even references to FOO that occur before the assignment still refer to the local variable and can raise an UnboundLocalError.

def a_func():
    BAR.append("bar")
    print(FOO)       #<--- "Freaky" UnboundLocalError occurs here!
    FOO = FOO + "foo" 

So inside a_func, FOO is a local variable. In the case where there is no print(FOO) statement, Python reaches the assignment and it evaluates the right-hand side first. It encounters the variable name, FOO, recognizes it as a local variable and asks what's its value? It has no value! So it raises an UnboundLocalError.

To fix, use global FOO to declare that the FOO inside a_func refers to a global variable:

FOO = "foo"
BAR = []

def a_func():
   global FOO
   BAR.append("bar") #ok
   FOO = FOO + "foo" assignment

In contrast, BAR.append('bar') works because Python first looks up the variable BAR -- it does not consider it a local variable since there was no assignment of the form BAR = .... It finds BAR in the global scope, then looks up its append method, and then mutates BAR. Thus you can mutate BAR but can't assign to FOO (without the global FOO statement.)

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the internal explanation. Lets bring this to a Closure (Bwhoeehaaaa)
2

No, it has nothing to do with the import. It would happen in a single module or script as well, even in the interacive interpreter.

A minimum example would be

a = 1
def f():
    a = a + 1

This assignment makes a a local variable. In this case, the global one is shadowed and thus inaccessible.

You can work around this situation with global if you want to change the global one:

a = 1
def f():
    global a
    a = a + 1

or with a differently named local variabl if you want to keep the changes locally:

a = 1
def f():
    b = a
    b = b + 1

Comments

0

I could be wrong, but could the scoping on FOO and BAR be the problem? It appears as if you've entered a different scope. Try marking FOO and BAR in your method as globals.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.