Python function scoping with import
Question: 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.


Answer: 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.)

