Variable scoping rules in Python?

joshua.davies at travelocity.com joshua.davies at travelocity.com
Mon Oct 8 16:17:36 CEST 2007


Ok, I'm relatively new to Python (coming from C, C++ and Java).  I'm
working on a program that outputs text that may be arbitrarily long,
but should still line up, so I want to split the output on a specific
column boundary.  Since I might want to change the length of a column,
I tried defining the column as a constant (what I would have made a
"#define" in C, or a "static final" in Java).  I defined this at the
top level (not within a def), and I reference it inside a function.
Like this:

COLUMNS = 80

def doSomethindAndOutputIt( ):
  ...
  for i in range( 0, ( len( output[0] ) / COLUMNS ) ):
    print output[0][ i * COLUMNS : i * COLUMNS + ( COLUMNS - 1 ) ]
    print output[1][ i * COLUMNS : i * COLUMNS + ( COLUMNS - 1 ) ]
    ..

etc. etc.  It works fine, and splits the output on the 80-column
boundary just like I want.

Well, I decided that I wanted "COLUMNS = 0" to be a special "don't
split anywhere" value, so I changed it to look like this:

COLUMNS = 80

def doSomethindAndOutputIt( ):
  ...
  if COLUMNS == 0:
    COLUMNS = len( output[ 0 ] )

  for i in range( 0, ( len( output[0] ) / COLUMNS ) ):
    print output[0][ i * COLUMNS : i * COLUMNS + ( COLUMNS - 1 ) ]
    print output[1][ i * COLUMNS : i * COLUMNS + ( COLUMNS - 1 ) ]
    ..

Now, when I run it, I get the following error:

Traceback (most recent call last):
  File "Test.py", line 140, in ?
    doSomethingAndOutput( input )
  File "Test.py", line 123, in doSomethingAndOutput
    if COLUMNS == 0:
UnboundLocalError: local variable 'COLUMNS' referenced before
assignment

I went back and re-read chapter 13 of "Learning Python", which talks
about variable scoping rules, and I can't figure out why Python is
saying this variable in Unbound.  It works if I insert:

  global COLUMNS

before the "if" statement... but I don't understand why.  Is the
interpreter scanning my entire function definition before executing
it, recognizing that I *might* assign COLUMNS to a value, and deciding
that it's a local on that basis?




More information about the Python-list mailing list