# Function scope

Take a moment to study the below code and predict the result before running it.

def outer_func():
def inner_func():
a = 9
print('inside inner_func, a is {:d} (id={:d})'.format(a, id(a)))
print('inside inner_func, b is {:d} (id={:d})'.format(b, id(b)))
print('inside inner_func, len is {:d} (id={:d})'.format(len,id(len)))

len = 2
print('inside outer_func, a is {:d} (id={:d})'.format(a, id(a)))
print('inside outer_func, b is {:d} (id={:d})'.format(b, id(b)))
print('inside outer_func, len is {:d} (id={:d})'.format(len,id(len)))
inner_func()

a, b = 6, 7
outer_func()
print('in global scope, a is {:d} (id={:d})'.format(a, id(a)))
print('in global scope, b is {:d} (id={:d})'.format(b, id(b)))
print('in global scope, len is', len, '(id={:d})'.format(id(len)))


This program defines a function, inner_func nested inside another, outer_func. After these definitions, the execution proceeds as follows:

1. Global variables a=6 and b=7 are initialized.
2. outer_func is called:
1. outer_func defines a local variable, len=2.
2. The values of a and b are printed; they don't exist in local scope and there isn't any enclosing scope, so Python searches for and finds them in global scope: their values (6 and 7) are output.
3. The value of local variable len (2) is printed.
4. inner_func is called:
1. A local variable, a=9 is defined.
2. The value of this local variable is printed.
3. The value of b is printed; b doesn't exist in local scope so Python looks for it in enclosing scope, that of outer_func. It isn't found there either, so Python proceeds to look in global scope where it is found: the value b=7 is printed.
4. The value of len is printed: len doesn't exist in local scope, but it is in the enclosing scope since len=2 is defined in outer_func: its value is output
3. After outer_func has finished execution, the values of a and b in global scope are printed.
4. The value of len is printed. This is not defined in global scope, so Python searches its own built-in names: len is the built-in function for determining the lengths of sequences. This function is itself an object and it provides a short string description of itself when printed.

Here is the output:

inside outer_func, a is 6 (id=232)
inside outer_func, b is 7 (id=264)
inside outer_func, len is 2 (id=104)
inside inner_func, a is 9 (id=328)
inside inner_func, b is 7 (id=264)
inside inner_func, len is 2 (id=104)
in global scope, a is 6 (id=232)
in global scope, len is <built-in function len> (id=977)


Note that in this example outer_func has (perhaps unwisely) redefined ("re-bound") the name len to the integer object 2. This means that the original len built-in function is not available within this function (and neither is it avaiable within the enclosed function, inner_func).