Variable scoping rules in Python?
Bruno Desthuilliers
bruno.42.desthuilliers at wtf.websiteburo.oops.com
Mon Oct 8 11:06:44 EDT 2007
joshua.davies at travelocity.com a écrit :
> 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.
FWIW :
http://docs.python.org/lib/module-textwrap.html
> 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 ) ]
> ..
Since you don't want to modify a global (and even worse, a CONSTANT),
the following code may be a bit cleaner:
def doSomethindAndOutputIt( ):
...
if COLUMNS == 0:
columns = len( output[ 0 ] )
else:
columns = COLUMNS
for i in range( 0, ( len( output[0] ) / COLUMNS ) ):
print output[0][ 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?
You name it. That's *exactly* what happens.
More information about the Python-list
mailing list