Nested function scope problem

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Sat Jul 22 15:20:32 EDT 2006


Josiah Manson a écrit :
> I found that I was repeating the same couple of lines over and over in
> a function and decided to split those lines into a nested function
> after copying one too many minor changes all over. The only problem is
> that my little helper function doesn't work! It claims that a variable
> doesn't exist. If I move the variable declaration, it finds the
> variable, but can't change it. Declaring the variable global in the
> nested function doesn't work either.
> 
> But, changing the variable in the containing scope is the whole purpose
> of this helper function.
> 
> I'm new to python, so there is probably some solution I haven't
> encountered yet. Could you please suggest a nice clean solution? The
> offending code is below. Thanks.
> 
> def breakLine(s):
> 	"""Break a string into a list of words and symbols.
> 	"""
> 	def addTok():
> 		if len(tok) > 0:

                 if tok:

An empty sequence evals to False in a boolean context.

> 			ls.append(tok)
> 			tok = ''
> 

First point: the nested function only have access to names that exists 
in the enclosing namespace at the time it's defined.

Second point: a nested function cannot rebind names from the enclosing 
namespace. Note that in Python, rebinding a name and modifying the 
object bound to a name are very distinct operations.

Third point : functions modifying their environment this way are usually 
considered bad form.

Here's a possible solution - but note that there are probably much 
better ways to get the same result...

def breakline(line):
   """Break a string into a list of words and symbols."""
   class TokenList(list):
     def append(self, token):
       if token:
         list.append(self, token)
       return ''

   tokens = TokenList()
   token = ''
   splitters = '?()&|:~,'
   whitespace = ' \t\n\r'
   specials = splitters + whitespace

   for char in line:
     if char in specials:
	token = tokens.append(token)
         if char in splitters:
           tokens.append(char)
     else:
       token += char

   tokens.append(token)
   return list(tokens)

(snip)



More information about the Python-list mailing list