Explaining why this works:
n = [0]
def list_access():
n[0] = n[0] + 1
return n
try:
print "\nlist_access:", list_access()
except UnboundLocalError, inst:
print " ERROR:\n", inst
And this throws the exception:
m = 0
def int_access():
m = m + 1
return m
try:
print "\nint_access:", int_access()
except UnboundLocalError, inst:
print " ERROR:\n", inst
To execute a source program, the Python compiler compiles your
original source into 'byte codes' – a form of your program that
is easier for the Python interpreter to later run. In generating this
byte code, the byte code compiler will determine which variable names
in a function are local to that function, (so alowing it to optimise
accesses to such local names).
The rule for determining if a variable is local to a function is:
- If there is a global statement for the name in the function
then the name is accessed from the global scope.
- If there is no global statement for the name, and if there
are assignments to the 'bare' name within the function then the name
is of local scope.
( A bare name assignment means assignment to a
name, where the name occurs without attribute references,
subscripts, or slicing s, just the bare name).
- Otherwise the name will be looked up in reverse order of all
enclosing scopes, until it is found.
In the second example, function int_access; name m is flagged as
local by the byte code compiler as the bare name is being assigned
to. The interpreter therefore looks for a value of m to increment
only in the local scope, cannot find a value, then raises the
UnboundLocalError exception.
In function list_access, the bare
name n is not assigned to, so n is found when looking back
through enclosing scopes.
References
http://groups.google.com/group/comp.lang.python/browse_frm/thread/db9955da70c4e0ca
http://www.python.org/doc/2.4/ref/global.html
END.