[Tutor] scoping rules

Kirby Urner urnerk@qwest.net
Sun, 06 Jan 2002 06:45:41 -0800


>
>Does this mean that i will not be able to increment a (908)
>(defined in the enclosing function) inside the inner function?
>
>hope i have framed my question properly.
>
>thanks
>karthik.

Local variables within a function override any variables
of the same name outside the function, unless you use
global.  Example:

  >>> def inc(n):
          n = n + 1
          print n


  >>> n = 10
  >>> inc(n)
  11
  >>> n  # n was unchanged
  10

But:

   >>> def inc():
           global n
           n = n + 1
           print n


   >>> n = 10
   >>> inc()
   11
   >>> n  # n was changed
   11

In general, it's not a great idea to have functions modify
global variables as a side effect.  A better approach is
have all necessary inputs passed as arguments and all
outputs returned via the return statement.

For example:

 >>> def func(x):
         a = 908
         def inc(x):
                 print "isnide func"
                 print "\tlocals",locals()
                 print "\tglobals",globals()
                 i =123
                 print "\tlocals again",locals()
                 x+=1            ###statement
                 return x
         print "ok",locals()
         a = inc(a)
         print a

Here the value to be modified comes through the
"front door" as an argument, and is returned through
the "back door" as a returned value, which is
rebound to variable 'a', duly incremented.  The
inc() function produces no side effects (i is
thrown away), unless we count the prints to
stdout.

But of course part of the reason for including a
function inside another function is you might want
to take advantage of one or more constants in the
enclosing scope.  This you can do:

  >>> def func():
         constant = 908
         def inc(x):
              x+= constant
              return x
         print "ok",locals()
         a = 87
         a = inc(a)
         return a

  >>> func()
  ok {'constant': 908, 'inc': <function inc at 0x01123220>}
  995

Here you are not rebinding constant by assignment, merely
making use of it as a part of the enclosing scope.  The
inner function has no problem with this, and this is part
of the incentive for enclosing functions inside of functions:
you get to treat the local scope of the outer function as
part of the global scope (but in this example, in a way
which doesn't try to modify global variables through side
effects).

Kirby