Question re local bindings in nested scopes

Kirby Urner urner at alumni.princeton.edu
Mon Jun 4 12:55:41 EDT 2001


I don't get why the following two functions, each with internal
functions that take advantage of lexical scoping (new in 2.1),
behave so differently:

  from __future__ import nested_scopes

  def spam(a,b):
      def bar():
          output = []
          print b
          print a
          output.append(a+1)
          return output
      return [x for x in bar()]

  def foo(a,b):
      def bar():
          output = []
          print b
          print a
          a += 1
          output.append(a)
          return output
      return [x for x in bar()]

  >>> spam(1,10)
  10
  1
  [2]
  >>> foo(1,10)
  10
  Traceback (most recent call last):
    File "<pyshell#16>", line 1, in ?
      foo(1,10)
    File "d:\program files\python21\ocn\test.py", line 38, in foo
      return [x for x in bar()]
    File "d:\program files\python21\ocn\test.py", line 34, in bar
      print a
  UnboundLocalError: local variable 'a' referenced before assignment

I can fix foo() by assigning a to s and doing the increment on s:

  def foo(a,b):
      def bar():
          output = []
          print b
          print a
          s = a   # added this line
          s += 1 # added this line
          output.append(s)
          return output
      return [x for x in bar()]

But should a=a+1 (or a += 1) really break the initial binding of a 
to the outer scope?  Is this intended?  Given a and b initialize to
the outer scope values just fine in spam(), it seems odd to unbind
an already initialized variable at "compile time" just because we 
add 1 to it.  Seems too subtle for its own good.  a=a+1 would seem 
a runtime operation on a variable that is already initialized at 
compile time thanks to lexical scoping.

Kirby

CC replies/insights to pdx4d at teleport.com and/or above address please




More information about the Python-list mailing list