python编程之执行带有局部副作用的代码
来源:互联网 发布:广联达梦龙网络计划 编辑:程序博客网 时间:2024/05/16 07:46
首先我们来做一个小实验:
>>>a=3>>>exec('b = a +1')>>>print(b)>>>14
然后我们在函数体内做同样的实验:
>>>def test():... a = 13 ... exec('b = a + 1')... print(b)...
运行结果却出现了错误:
NameError: global name ‘b’ is not defined
要解决此类问题,需要使用locals()函数在调用exec()之前获取一个保存了局部变量的字典,紧接着,就可以从本地字典中提取出修改过的值。示例如下:
def test(): a = 13 loc = locals() exec('b = a + 1') b = loc['b'] print(b)
运行这个函数之后结果为正确的 14
下面我们来进行一番讨论
要一般编程过程中要正确使用exec()其实是非常具有技巧性的,事实上,大多数考虑使用exec()的情况下,可能存在更加优雅的解决方案(例如装饰器、闭包、元类等)。
如果必须要使用exec(),那么可以参考以下原则:
默认情况下,exec()在调用方的局部或者全局作用域中执行代码。然而在函数内部,传递给exec()的局部作用是一个字典,而这个字典是实际局部变量的一份拷贝。因此,如果exec()中执行的代码对全局变量做出了任何修改,这个修改绝不会反应到实际的局部变量中去。以下示例将作出解释:
def test1(): a = 0 exec('a += 1') print(a)
执行此函数结果为 0 ,可见当调用locals()来获取局部变量时,传递给exec()的是局部变量的拷贝。而在exec()执行完毕之后,通过检查字典的值,就能获取到修改过的变量值。下例可验证这一点:
def test2(): a = 0 loc = locals() print('before:',loc) exec('a += 1') print('after:',loc) #a = loc['a'] print(a)
执行结果如下:
before: {'a': 0} after: {'a': 1, 'loc': {...}} 0
观察最后一步的输出可以得知,除非从loc中将修改过的值写回x,否则变量x会保持不变。
每次使用locals()时都要小心操作的顺序问题。每次调用时,locals()将会接受局部变量的当前值,然后覆盖字典中的对应条目。请看以下示例:
def test3(): a = 0 loc = locals() print(loc) exec('a += 1') print(loc) locals() print(loc)
执行结果如下
{'a': 0}{'loc': {...}, 'a': 1}{'loc': {...}, 'a': 0}
注意最后对locals()的调用是如何导致x被覆盖的。
除了使用locals()之外,另一种可选的方式是自己创建字典并传递给exec()。示例如下:
def test4(): a = 13 loc = {'a':a} glb={ } exec('b = a + 1',glb,loc) b = loc['b'] print(b)
最后的运行结果为14
对于大部分针对exec()的应用,这就够了。我们需要确保exec()中访问的变量在全局和局部字典中经过你恰当的初始化。
最后提示:
在使用exec()时,想一想其他的可选方案,就像讨论一开始列出的类似选项
- python编程之执行带有局部副作用的代码
- Learning Python(17)--多线程编程之线程的局部变量
- 编程之美3.11扩展问题 简单并带有错误的环形单链表检测代码
- 黑马程序员--Java编程之代码执行的流程控制
- python——执行带有%的sql执行报错解决方法
- 《编程导论(Java)·3.1.2 方法》之 副作用
- 静态代码块、构造代码块、局部代码块、构造方法的执行顺序
- 构造代码块,静态代码块,局部代码块与new对象时,执行的次序
- 关于空指针异常的副作用及代码规范问题
- 【Java基础知识】代码块的执行顺序(静态、构造、局部代码块)
- Python编程基础之十三Python执行环境
- 提高python代码的执行效率
- Python 执行代码的两种方式
- 带有身份验证的JAVAMAIL编程
- 带有身份验证的JAVAMAIL编程
- 实现带有验证码的ajax局部刷新登录界面
- 执行带有输出参数的存储过程
- [代码笔记] python 之socket编程(一)
- sort2——随机数生成测试样例
- JavaSE_笔试题_多选选择题1
- iOS Hacker obfuscator-llvm Xcode集成配置
- spring
- RHEL6.5环境的基础配置
- python编程之执行带有局部副作用的代码
- 最强表格渲染框架
- Android Services设置ProgressBar(进度条的值)
- hdu3118(二分图位判断)
- 好文链接
- CentOS 7.0关闭默认防火墙启用iptables防火墙
- 读书笔记-天机妙算刘伯温-3
- Ice_cream’s world II
- Java虚拟机---初识Java