[Python-ideas] *var()*
Steven D'Aprano
steve at pearwood.info
Fri Jan 3 02:18:34 CET 2014
On Thu, Jan 02, 2014 at 02:16:39PM -1000, Guido van Rossum wrote:
> On Thu, Jan 2, 2014 at 3:35 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> > I would have guessed that you could get this working with eval, but if
> > there is such a way, I can't work it out.
>
> It's trivial if you directly invoke eval():
That's what I thought too, but I get surprising results with
nonlocals.
a = b = "global"
def test1():
b = c = "nonlocal"
def inner():
d = "local"
return (a, b, c, d)
return inner()
def test2():
b = c = "nonlocal"
def inner():
d = "local"
c # Need this or the function fails with NameError.
return (eval('a'), eval('b'), eval('c'), eval('d'))
return inner()
assert test1() == test2() # Fails.
test1() returns ('global', 'nonlocal', 'nonlocal', 'local'), which is
what I expect. But test2() returns ('global', 'global', 'nonlocal', 'local'),
which surprises me.
If I understand what is going on in test2's inner function, eval('b')
doesn't see the nonlocal b so it picks up the global b. (If there is no
global b, you get NameError.) But eval('c') sees the nonlocal c because
we have a closure, due to the reference to c in the previous line.
If there's a way to get eval('b') to return "nonlocal" without having a
closure, I don't know it. This suggests to me that you can't reliably
look-up a nonlocal from an inner function using eval.
--
Steven
More information about the Python-ideas
mailing list