为什么Python的exec()函数在函数内外的运行表现不一致?
exec在函数内部无法创建可直接访问的局部变量的原因
这是Python函数作用域的静态编译规则和exec的动态执行特性冲突导致的,具体逻辑如下:
- 全局作用域下的变量访问是动态查找的:示例1的exec在全局作用域执行,直接把
greeting_one写入了全局命名空间字典,后续print访问全局变量时会实时查全局字典,因此可以正常拿到变量值。 - 函数局部作用域采用静态绑定机制:Python在编译函数的字节码阶段,就会扫描函数内所有显式写的赋值语句,提前确定哪些变量属于局部变量,访问局部变量时会直接用预先分配的索引取值,不会动态查局部命名空间字典。exec执行的字符串中的赋值是运行时才生效的,编译阶段完全感知不到,因此Python不会把
greeting_two识别为函数的局部变量,运行时会优先去全局命名空间找这个变量,找不到就抛出未定义报错。 - 补充验证:你可以在示例2的exec执行后加一行
print(locals()),会看到greeting_two确实存在于当前局部命名空间的字典里,只是解释器不会主动去这个字典里找这个变量而已。
修复方案
下面是两种常用的修复方式:
方案1:从locals()字典中主动读取变量
如果确实要从exec的当前局部命名空间取变量,直接显式从locals()返回的字典里取值即可:
def example_function(): string_two = 'greeting_two = "hi"' exec(string_two) print(locals()['greeting_two']) example_function()
方案2:给exec指定独立的命名空间(更安全)
为了避免exec污染当前作用域,推荐单独传一个字典作为exec的命名空间,执行完成后直接从这个字典取变量:
def example_function(): string_two = 'greeting_two = "hi"' ns = {} exec(string_two, globals(), ns) print(ns['greeting_two']) example_function()
内容的提问来源于stack exchange,提问作者Mariusmarten
相关产品推荐
相关产品推荐

