
A Python Mystery - dcrosta
https://gist.github.com/2562350
======
revelation
The issue seems to be that CPython is optimizing the locals access for the
exec_code_object_and_return_x by using indices into the array, instead of the
normal lookup by name (which, by incident, is what the compiled code uses).

If I understand <http://bugs.python.org/issue4831> correctly, CPython 2.7
should not be optimizing the locals access in this way with an exec statement
present.

------
maxk42
Is it possible x is referring to the memory where x had previously been
allocated?

~~~
dcrosta
It turns out that this is not actually as surprising as I had first thought --
del unbinds a variable from the (local) scope. Since exec results in a new
Python frame, it is in that frame's scope that x is deleted, not in the outer
frame (of the function exec_code_object_and_return_x).

I'm in the process of blogging about this and other quirks of exec -- I'll
post back here once that's up.

~~~
revelation
At least for Python 2.7, you would expect the code run with exec to share the
locals and globals with the environment where you called exec from. Thats why
the x = x + 1 works, after all.

~~~
dcrosta
After reading through the bug you linked, now I agree with your statement and
not with my first comment here. Will the madness never end?

------
halayli
Speaking of CPython optimizations

> x = 124236

> y = 124237

> y -= 1

> id(x)

140474467900408

> id(y)

140474467900360

> x is y

False

> x = 1

> y = 2

> y -= 1

> id(x)

140558102245816

> id(y)

140558102245816

> x is y

True

~~~
sparky
CPython interns ints in [-5, 256]. Seems like a reasonable common-case
optimization to me.

~~~
halayli
Agreed. It didn't surprise me much, but it makes things less consistent.

