python - 为什么 exec() 中的符号定义语句有时对本地符号表没有影响?

标签 python python-3.x exec local-variables symbol-table

以下代码片段按预期工作:

def test():
    print(f'local symbol table before exec : {locals()}')
    exec('a = 0')
    print(f'local symbol table after exec  : {locals()}')

test()
# printed result:
# local symbol table before exec : {}
# local symbol table after exec  : {'a': 0}
但是,一旦我添加了符号定义语句 a = 1test 结尾函数,似乎 exec语句对本地符号表没有影响:
def test():
    print(f'local symbol table before exec : {locals()}')
    exec('a = 0')
    print(f'local symbol table after exec  : {locals()}')
    a = 1

test()
# printed result:
# local symbol table before exec : {}
# local symbol table after exec  : {}
那么,为什么会这样呢?
这是我的猜测:在函数内部静态定义的符号将在编译时以某种方式保留,如果符号已经保留,则在 exec 函数内部动态调用的任何符号定义语句都无法修改本地符号表。
真的吗?在编译期间实际发生了什么?

额外测试 1 : 用 'a = 0\nprint(locals())' 替换 exec 参数
def test():
    print(f'local symbol table before exec : {locals()}')
    exec('a = 0\nprint(locals())')
    print(f'local symbol table after exec  : {locals()}')


test()
# printed result:
# local symbol table before exec : {}
# {'a': 0}
# local symbol table after exec  : {'a': 0}
def test():
    print(f'local symbol table before exec : {locals()}')
    exec('a = 0\nprint(locals())')
    print(f'local symbol table after exec  : {locals()}')
    a = 1


test()
# printed result:
# local symbol table before exec : {}
# {'a': 0}
# local symbol table after exec  : {}
如我们所见,符号aexec() 期间已成功添加到本地符号表中执行,但之后随着 a = 1 的存在神奇地消失了.

额外测试 2 :添加return a = 1 之前的声明
def test():
    print(f'local symbol table before exec : {locals()}')
    exec('a = 0\nprint(locals())')
    print(f'local symbol table after exec  : {locals()}')
    return


test()
# printed result:
# local symbol table before exec : {}
# {'a': 0}
# local symbol table after exec  : {'a': 0}
def test():
    print(f'local symbol table before exec : {locals()}')
    exec('a = 0\nprint(locals())')
    print(f'local symbol table after exec  : {locals()}')
    return
    a = 1


test()
# printed result:
# local symbol table before exec : {}
# {'a': 0}
# local symbol table after exec  : {}
a = 1在第二个 test() 中无法访问功能,但它仍然影响 exec() 的行为.
甚至 dis()函数来自 dis模块无法区分这两个 test()职能。输出完全相同,如下所示:
  5           0 LOAD_GLOBAL              0 (print)
              2 LOAD_CONST               1 ('local symbol table before exec : ')
              4 LOAD_GLOBAL              1 (locals)
              6 CALL_FUNCTION            0
              8 FORMAT_VALUE             0
             10 BUILD_STRING             2
             12 CALL_FUNCTION            1
             14 POP_TOP

  6          16 LOAD_GLOBAL              2 (exec)
             18 LOAD_CONST               2 ('a = 0\nprint(locals())')
             20 CALL_FUNCTION            1
             22 POP_TOP

  7          24 LOAD_GLOBAL              0 (print)
             26 LOAD_CONST               3 ('local symbol table after exec  : ')
             28 LOAD_GLOBAL              1 (locals)
             30 CALL_FUNCTION            0
             32 FORMAT_VALUE             0
             34 BUILD_STRING             2
             36 CALL_FUNCTION            1
             38 POP_TOP

  8          40 LOAD_CONST               0 (None)
             42 RETURN_VALUE

最佳答案

根据documentation :

Note: The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.


所以我相信这属于“意外行为”,但我想你可以去执行 exec()真正深入并理解。

关于python - 为什么 exec() 中的符号定义语句有时对本地符号表没有影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67642662/

相关文章:

javascript - 您如何使用 Electron 应用程序检查文件是否存在于本地

python - 在 python 中将位数组写入文件?

python - 使用 pxssh 时无法为预期导入名称 'spawn'

python - 从父类(super class)访问 Django 子类方法

python - 如何根据第一个元素对嵌套列表进行分组?

nginx - PHP exec() 不运行所有命令

python:哪个文件更新了多少时间

python - django计数注释字段

python-3.x - 如何修复 'Can' t 分配请求的地址'。即使我在 mac 上用 python 尝试了许多不同的端口

ant - 如何从 Ant 构建脚本执行交互式应用程序?