Ala*_* Xu 10 python exec local-variables symbol-table python-3.x
以下代码片段按预期工作:
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}
Run Code Online (Sandbox Code Playgroud)
但是,一旦我a = 1在test函数末尾添加了符号定义语句,该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 : {}
Run Code Online (Sandbox Code Playgroud)
那么,为什么会发生这种情况?
这是我的猜测:在函数内部静态定义的符号将在编译时以某种方式被保留,如果符号已经被保留,则在 exec 函数内部动态调用的任何符号定义语句将无法修改本地符号表。
真的吗?编译期间实际发生了什么?
额外测试 1:将 exec 参数替换为'a = 0\nprint(locals())'
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}
Run Code Online (Sandbox Code Playgroud)
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 : {}
Run Code Online (Sandbox Code Playgroud)
正如我们所见,符号a在exec()执行过程中被成功添加到本地符号表中,但之后它随着 的存在神奇地消失了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}
Run Code Online (Sandbox Code Playgroud)
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 : {}
Run Code Online (Sandbox Code Playgroud)
该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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
167 次 |
| 最近记录: |