Nested function scope problem

Simon Forman rogue_pedro at yahoo.com
Fri Jul 21 22:36:37 EDT 2006


Gerhard Fiedler wrote:
> On 2006-07-21 21:05:22, Josiah Manson wrote:
>
> > 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.
>
> I'm no Python specialist, so here's just some guesses... I don't know how
> to make variables known inside the inner function. It seems just using the
> names there overrides the outside names. It also seems that local variables
> are in some kind of dictionary; so maybe you can access them through that
> somehow.
>
> One other solution (a bit ugly) would be to make this a class with two
> static methods (breakLine and _addTok) and two static attributes (_ls and
> _tok).
>
> Still another (also ugly) would be to pass both tok and ls to addTok() and
> pass tok back out again. (I think ls doesn't have to be passed back,
> because it is a list and so its data gets modified. tok's data doesn't get
> modified, so local changes don't propagate to the outside.)
>
> Gerhard

That third option seems to work fine.

def breakLine(s):
    """Break a string into a list of words and symbols.
    """

    def addTok(tok, ls):
        if len(tok) > 0:
            ls.append(tok)
            tok = ''
        return tok

    ls = []
    tok = ''
    splitters = '?()&|:~,'
    whitespace = ' \t\n\r'

    for c in s:
        if c in splitters:
            tok = addTok(tok, ls)
            ls.append(c)
        elif c in whitespace:
            tok = addTok(tok, ls)
        else:
            tok = tok + c

    tok = addTok(tok, ls)

    return ls

#some tests to make sure it works
print breakLine('carolina(Prada):cat(X,Y)')
print breakLine('trouble :bird (X ) &cat ( Y )')
print breakLine('?trouble')

# Prints:
['carolina', '(', 'Prada', ')', ':', 'cat', '(', 'X', ',', 'Y', ')']
['trouble', ':', 'bird', '(', 'X', ')', '&', 'cat', '(', 'Y', ')']
['?', 'trouble']




More information about the Python-list mailing list