Python 在局部变量域中执行代码


Posted in Python onAugust 07, 2020

问题

你想在使用范围内执行某个代码片段,并且希望在执行后所有的结果都不可见。

解决方案

为了理解这个问题,先试试一个简单场景。首先,在全局命名空间内执行一个代码片段:

>>> a = 13
>>> exec('b = a + 1')
>>> print(b)
14
>>>

然后,再在一个函数中执行同样的代码:

>>> def test():
...   a = 13
...   exec('b = a + 1')
...   print(b)
...
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in test
NameError: global name 'b' is not defined
>>>

可以看出,最后抛出了一个NameError异常,就跟在 exec() 语句从没执行过一样。 要是你想在后面的计算中使用到 exec() 执行结果的话就会有问题了。

为了修正这样的错误,你需要在调用 exec() 之前使用 locals() 函数来得到一个局部变量字典。 之后你就能从局部字典中获取修改过后的变量值了。例如:

>>> def test():
...   a = 13
...   loc = locals()
...   exec('b = a + 1')
...   b = loc['b']
...   print(b)
...
>>> test()
14
>>>

讨论

实际上对于 exec() 的正确使用是比较难的。大多数情况下当你要考虑使用 exec() 的时候, 还有另外更好的解决方案(比如装饰器、闭包、元类等等)。

然而,如果你仍然要使用 exec() ,本节列出了一些如何正确使用它的方法。 默认情况下,exec() 会在调用者局部和全局范围内执行代码。然而,在函数里面, 传递给 exec() 的局部范围是拷贝实际局部变量组成的一个字典。 因此,如果 exec() 如果执行了修改操作,这种修改后的结果对实际局部变量值是没有影响的。 下面是另外一个演示它的例子:

>>> def test1():
...   x = 0
...   exec('x += 1')
...   print(x)
...
>>> test1()
0
>>>

上面代码里,当你调用 locals() 获取局部变量时,你获得的是传递给 exec() 的局部变量的一个拷贝。 通过在代码执行后审查这个字典的值,那就能获取修改后的值了。下面是一个演示例子:

>>> def test2():
...   x = 0
...   loc = locals()
...   print('before:', loc)
...   exec('x += 1')
...   print('after:', loc)
...   print('x =', x)
...
>>> test2()
before: {'x': 0}
after: {'loc': {...}, 'x': 1}
x = 0
>>>

仔细观察最后一步的输出,除非你将 loc 中被修改后的值手动赋值给x,否则x变量值是不会变的。

在使用 locals() 的时候,你需要注意操作顺序。每次它被调用的时候, locals() 会获取局部变量值中的值并覆盖字典中相应的变量。 请注意观察下下面这个试验的输出结果:

>>> def test3():
...   x = 0
...   loc = locals()
...   print(loc)
...   exec('x += 1')
...   print(loc)
...   locals()
...   print(loc)
...
>>> test3()
{'x': 0}
{'loc': {...}, 'x': 1}
{'loc': {...}, 'x': 0}
>>>
>>> def test3():
...   x = 0
...   loc = locals()
...   print(loc)
...   exec('x += 1')
...   print(loc)
...   locals()
...   print(loc)
...
>>> test3()
{'x': 0}
{'loc': {...}, 'x': 1}
{'loc': {...}, 'x': 0}
>>>

注意最后一次调用 locals() 的时候x的值是如何被覆盖掉的。

作为 locals() 的一个替代方案,你可以使用你自己的字典,并将它传递给 exec() 。例如:

>>> def test4():
...   a = 13
...   loc = { 'a' : a }
...   glb = { }
...   exec('b = a + 1', glb, loc)
...   b = loc['b']
...   print(b)
...
>>> test4()
14
>>>

大部分情况下,这种方式是使用 exec() 的最佳实践。 你只需要保证全局和局部字典在后面代码访问时已经被初始化。

还有一点,在使用 exec() 之前,你可能需要问下自己是否有其他更好的替代方案。 大多数情况下当你要考虑使用 exec() 的时候, 还有另外更好的解决方案,比如装饰器、闭包、元类,或其他一些元编程特性。

以上就是Python 在局部变量域中执行代码的详细内容,更多关于Python 局部变量域的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
17个Python小技巧分享
Jan 23 Python
Python批量重命名同一文件夹下文件的方法
May 25 Python
浅谈python中的数字类型与处理工具
Aug 02 Python
Python 网页解析HTMLParse的实例详解
Aug 10 Python
python实现xlsx文件分析详解
Jan 02 Python
python获取酷狗音乐top500的下载地址 MP3格式
Apr 17 Python
django之对FileField字段的upload_to的设定方法
Jul 28 Python
Python使用matplotlib绘制三维参数曲线操作示例
Sep 10 Python
python使用建议与技巧分享(二)
Aug 17 Python
关于python中导入文件到list的问题
Oct 31 Python
PyQT5速成教程之Qt Designer介绍与入门
Nov 02 Python
python实现excel公式格式化的示例代码
Dec 23 Python
Python如何创建装饰器时保留函数元信息
Aug 07 #Python
python的launcher用法知识点总结
Aug 07 #Python
详解PyQt5中textBrowser显示print语句输出的简单方法
Aug 07 #Python
PyQt5的相对布局管理的实现
Aug 07 #Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
Aug 07 #Python
Python configparser模块封装及构造配置文件
Aug 07 #Python
Python logging模块进行封装实现原理解析
Aug 07 #Python
You might like
php的日期处理函数及uchome的function_coomon中日期处理函数的研究
2011/01/12 PHP
php摘要生成函数(无乱码)
2012/02/04 PHP
采用thinkphp自带方法生成静态html文件详解
2014/06/13 PHP
js中的window.open返回object的错误的解决方法
2009/08/15 Javascript
用jQuery技术实现Tab页界面之二
2009/09/21 Javascript
jquery实现效果比较好的table选中行颜色
2014/03/25 Javascript
Easyui form combobox省市区三级联动
2016/01/13 Javascript
jQuery中的基本选择器用法学习教程
2016/04/14 Javascript
ng-options和ng-checked在表单中的高级运用(推荐)
2017/01/21 Javascript
详解axios在node.js中的post使用
2017/04/27 Javascript
激动人心的 Angular HttpClient的源码解析
2017/07/10 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
2017/08/31 Javascript
利用jquery如何从json中读取数据追加到html中
2017/12/01 jQuery
Node.js Koa2使用JWT进行鉴权的方法示例
2018/08/17 Javascript
微信小程序常用赋值方法小结
2019/04/30 Javascript
JS实现页面数据懒加载
2020/02/13 Javascript
python使用pil生成缩略图的方法
2015/03/26 Python
Python中统计函数运行耗时的方法
2015/05/05 Python
Python3.6笔记之将程序运行结果输出到文件的方法
2018/04/22 Python
Python判断有效的数独算法示例
2019/02/23 Python
Python3.5多进程原理与用法实例分析
2019/04/05 Python
python程序 线程队列queue使用方法解析
2019/09/23 Python
python获取array中指定元素的示例
2019/11/26 Python
CSS3中的@keyframes关键帧动画的选择器绑定
2016/06/13 HTML / CSS
使用HTML5捕捉音频与视频信息概述及实例
2018/08/22 HTML / CSS
H5新属性audio音频和video视频的控制详解(推荐)
2016/12/09 HTML / CSS
Auguste The Label官网:澳大利亚一家精品女装时尚品牌
2020/06/14 全球购物
体育教师求职信
2014/05/24 职场文书
节约用水标语
2014/06/11 职场文书
小学绿色学校申报材料
2014/08/23 职场文书
员工激励培训演讲稿
2014/09/16 职场文书
社区党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
安全承诺书
2015/01/19 职场文书
大学毕业生自我评价
2015/03/02 职场文书
运动会加油稿50字
2015/07/21 职场文书
SpringBoot使用ip2region获取地理位置信息的方法
2022/06/21 Java/Android