0
点赞
收藏
分享

微信扫一扫

PythonNote041---exec变量作用域问题


Intro

  分析时,常常拼接字符串,作为代码执行。此时会调用exec方法,在命令行或者jupyter中执行,exec执行的变量,在外部可以引用。而嵌套在函数内部时,则不能引用。看几个例子:

exec_str ="""
a = 1
"""
exec(exec_str)
print(f'a={a}')

a=1

def exe_f():
exec_str = f"""
fun_y = 1
print(f"exec_str:fun_y=",fun_y)
"""
exec(exec_str)
print(f"exe_f:fun_y=",fun_y)

exe_f()

exec_str:fun_y= 1



---------------------------------------------------------------------------

NameError Traceback (most recent call last)

~\AppData\Local\Temp\ipykernel_24724\1254702322.py in <module>
7 print(f"exe_f:fun_y=",fun_y)
8
----> 9 exe_f()


~\AppData\Local\Temp\ipykernel_24724\1254702322.py in exe_f()
5 """
6 exec(exec_str)
----> 7 print(f"exe_f:fun_y=",fun_y)
8
9 exe_f()


NameError: name 'fun_y' is not defined

原理见​​ref[1]​​,简言之,exec时,变量fun_y并没有注册到局部空间,因此引用时获取失败。

解法

有几种方法,依次看下

把exec执行结果保存到globals()

def exe_f():
exec_str = f"""
fun_y = 1
print(f"exec_str:fun_y=",fun_y)
"""
exec(exec_str,globals())
print(f"exe_f:fun_y=",fun_y)

exe_f()
print(f"globals:fun_y=",fun_y)

exec_str:fun_y= 1
exe_f:fun_y= 1
globals:fun_y= 1

该方法可能会导致全局变量被污染

自定义字典

def exe_f():
self_dict = {}
exec_str = f"""
fun_y1 = 1
print(f"exec_str:fun_y1=",fun_y1)
"""
exec(exec_str,globals(),self_dict)
print(f"exe_f:fun_y=",self_dict['fun_y1'])

exe_f()
var_name = 'fun_y1'
print(f'locals() {var_name}:{locals().get(var_name, None)}')

exec_str:fun_y1= 1
exe_f:fun_y= 1
locals() fun_y1:None

此时不会污染全局变量

Ref


                               2022-11-27 于南京市江宁区


举报

相关推荐

变量作用域

Java变量作用域

Python变量作用域

变量常量作用域

变量、常量、作用域

JavaScript变量作用域

变量 常量 作用域

类变量的作用域

0 条评论