Nested function scope problem
Bruno Desthuilliers
onurb at xiludom.gro
Mon Jul 24 05:06:30 EDT 2006
danielx wrote:
> Bruno Desthuilliers wrote:
>
>>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 = ''
>>>
>
>
> I can't figure out why Josiah's breakLine function won't work either. I
> know Josiah has had his problem resolved, but I'd still like to know
> why his func won't work. I'd like to redirect this discussion in that
> direction, if I may.
>
>
>>First point: the nested function only have access to names that exists
>>in the enclosing namespace at the time it's defined.
oops - Sorry, said an obvious stupidity here (was very tired, should not
have answered at all...)
>
> Coming from lisp, that doesn't make very much sense, and I'm not sure
> that's true. If you move the def for addTok bellow the lines that
> initialize the locals of breakLines, you still get the same problem.
of course.
>
>>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.
>
>
> I'm not sure that's the problem, because when I ran the debugger, the
> problem is with the line that says if len(tok), not the one bellow it
> which says tok = "".
That's a side-effect of rebinding tok - it makes the name local. Even if
the rebiding is done *after* first use of the name...
>
>>Third point : functions modifying their environment this way are usually
>>considered bad form.
>
>
> Again, this is coming from lisp, but I don't see anything wrong with
> that :P.
> ***
>
> After some experimentation, I am completely baffeled as to why
> breakLine won't work. Here is an example of one of the things I did,
> which I believe exactly mimics what breakLine does:
>
>>>>def outer():
>
> ... def inner():
> ... if outerLocal:
> ... return "I hear you, 'hello world'."
> ... else:
> ... return "Come again?"
> ... outerLocal = "hello world"
> ... return inner()
> ...
>
>>>>outer()
>
> "I hear you, 'hello world'."
>
> As I said, I believe the line which sets tok should break (quietly),
> but not the line which tests tok. My experiment seems to confirm
> this...
You did not rebind 'outerLocal' in your above code.
> One thing I can understand is why the line tok = "" in addTok won't
> work. This is because when Python sees that line, it should create a
> new local variable in the scope of addTok.
Yes. But this local name is referenced before assignment.
> Once addTok returns, that
> variable is lost. That's pretty deep, now that I've thought about it...
>
(snip)
Sorry once again for the obvious stupidity I wrote as first point. Next
time I'll go to bed instead, I promise :(
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"
More information about the Python-list
mailing list