Behavior of exec function in Python 2 and Python 3

前端 未结 4 999
北海茫月
北海茫月 2020-11-22 08:34

Following code gives different output in Python2 and in Python3:

from sys import version

print(version)

def execute(a, st):
    b         


        
4条回答
  •  心在旅途
    2020-11-22 09:22

    I'd say it's a bug of python3.

    def u():
        exec("a=2")
        print(locals()['a'])
    u()
    

    prints "2".

    def u():
        exec("a=2")
        a=2
        print(a)
    u()
    

    prints "2".

    But

    def u():
        exec("a=2")
        print(locals()['a'])
        a=2
    u()
    

    fails with

    Traceback (most recent call last):
      File "", line 1, in 
      File "", line 3, in u
    KeyError: 'a'
    

    --- EDIT --- Another interesting behaviour:

    def u():
        a=1
        l=locals()
        exec("a=2")
        print(l)
    u()
    def u():
        a=1
        l=locals()
        exec("a=2")
        locals()
        print(l)
    u()
    

    outputs

    {'l': {...}, 'a': 2}
    {'l': {...}, 'a': 1}
    

    And also

    def u():
        l=locals()
        exec("a=2")
        print(l)
        print(locals())
    u()
    def u():
        l=locals()
        exec("a=2")
        print(l)
        print(locals())
        a=1
    u()
    

    outputs

    {'l': {...}, 'a': 2}
    {'l': {...}, 'a': 2}
    {'l': {...}, 'a': 2}
    {'l': {...}}
    

    Apparently, the action of exec on locals is the following:

    • If a variable is set within exec and this variable was a local variable, then exec modifies the internal dictionary (the one returned by locals()) and does not return it to its original state. A call to locals() updates the dictionary (as documented in section 2 of python documentation), and the value set within exec is forgotten. The need of calling locals() to update the dictionary is not a bug of python3, because it is documented, but it is not intuitive. Moreover, the fact that modifications of locals within exec don't change the locals of the function is a documented difference with python2 (the documentation says "Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns"), and I prefer the behaviour of python2.
    • If a variable is set within exec and this variable did not exist before, then exec modifies the internal dictionary unless the variable is set afterwards. It seems that there is a bug in the way locals() updates the dictionary ; this bug gives access to the value set within exec by calling locals() after exec.

提交回复
热议问题