Learning Scientific Programming with Python (2nd edition)
E2.28: 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:
- Global variables
a=6andb=7are initialized. outer_funcis called:outer_funcdefines a local variable,len=2.- The values of
aandbare 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. - The value of local variable
len(2) is printed. inner_funcis called:- A local variable,
a=9is defined. - The value of this local variable is printed.
- The value of
bis printed;bdoesn't exist in local scope so Python looks for it in enclosing scope, that ofouter_func. It isn't found there either, so Python proceeds to look in global scope where it is found: the valueb=7is printed. - The value of
lenis printed:lendoesn't exist in local scope, but it is in the enclosing scope sincelen=2is defined inouter_func: its value is output
- A local variable,
- After
outer_funchas finished execution, the values ofaandbin global scope are printed. - The value of
lenis printed. This is not defined in global scope, so Python searches its own built-in names:lenis 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, b is 7 (id=264)
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).