Hacker News new | ask | show | jobs
by Erwin 2949 days ago
In Python 2, the bytecode optimization that lets you access variables by index is turned off if your function has exec code in it that may modify locals.

So if your function is:

   def foo(): exec "a=1"; return a
Then running dis.dis on foo to disassemble the bytecode it you will see:

              8 LOAD_NAME                0 (a)
while you normally would see:

              6 LOAD_FAST                0 (a)
You can't use the exec in locals thing in Python 3 at all I believe.
2 comments

I just tested it in Python3:

    def foo():
        exec("a=1")
        return a

    print(foo())
Fails with a NameError:

    Traceback (most recent call last):
      File "test.py", line 5, in <module>
        print(foo())
      File "test.py", line 3, in foo
        return a
    NameError: name 'a' is not defined
I get the same error with your example, but this works fine (Python 3.6.4):

    exec("a = 1")
    print(a)
This will print "1".
That is because the exec runs in the global scope. When Python sees a variable that is not assigned to in the local scope, it is assumed to be a global variable, so when exec creates a new local variable, the load still fails because it looks into the globals dictionary.

But you can do this:

  def foo():
    exec("a = 1")
    return locals()['a']
Ahh, I see, this makes more sense. Thanks for the clarification!