Confused by Python and nested scoping (2.4.3)

Ben Cartwright bencvt at gmail.com
Wed Apr 19 20:05:29 EDT 2006


Sean Givan wrote:
> def outer():
> 	val = 10
> 	def inner():
> 		print val
> 		val = 20
> 	inner()
> 	print val
>
> outer()
>
> ..I expected to print '10', then '20', but instead got an error:
>
>    print val
> UnboundLocalError: local variable 'val' referenced before assignment.
>
> I'm thinking this is some bug where the interpreter is getting ahead of
> itself, spotting the 'val = 20' line and warning me about something that
> doesn't need warning.  Or am I doing something wrong?


Short answer:  No, it's not a Python bug.  If inner() must modify
variables defined in outer()'s scope, you'll need to use a containing
object.  E.g.:

  class Storage(object):
      pass
  def outer():
      data = Storage()
      data.val = 10
      def inner():
          print data.val
          data.val = 20
      inner()
      print data.val

Long answer:

The interpreter (actually, the bytecode compiler) is indeed looking
ahead.  This is by design, and is why the "global" keyword exists.  See
http://www.python.org/doc/faq/programming/#what-are-the-rules-for-local-and-global-variables-in-python

Things get more complex than that when nested function scopes are
involved.  But again, the behavior you observed is a design decision,
not a bug.  By BDFL declaration, there is no "parentscope" keyword
analogous to "global".  See PEP 227, specifically the "Rebinding names
in enclosing scopes" section: http://www.python.org/dev/peps/pep-0227/

Hope that helps,
--Ben




More information about the Python-list mailing list