python编程之执行带有局部副作用的代码
2017-07-15 00:29
99 查看
首先我们来做一个小实验:
然后我们在函数体内做同样的实验:
运行结果却出现了错误:
NameError: global name ‘b’ is not defined
要解决此类问题,需要使用locals()函数在调用exec()之前获取一个保存了局部变量的字典,紧接着,就可以从本地字典中提取出修改过的值。示例如下:
运行这个函数之后结果为正确的 14
下面我们来进行一番讨论
要一般编程过程中要正确使用exec()其实是非常具有技巧性的,事实上,大多数考虑使用exec()的情况下,可能存在更加优雅的解决方案(例如装饰器、闭包、元类等)。
如果必须要使用exec(),那么可以参考以下原则:
默认情况下,exec()在调用方的局部或者全局作用域中执行代码。然而在函数内部,传递给exec()的局部作用是一个字典,而这个字典是实际局部变量的一份拷贝。因此,如果exec()中执行的代码对全局变量做出了任何修改,这个修改绝不会反应到实际的局部变量中去。以下示例将作出解释:
执行此函数结果为 0 ,可见当调用locals()来获取局部变量时,传递给exec()的是局部变量的拷贝。而在exec()执行完毕之后,通过检查字典的值,就能获取到修改过的变量值。下例可验证这一点:
执行结果如下:
观察最后一步的输出可以得知,除非从loc中将修改过的值写回x,否则变量x会保持不变。
每次使用locals()时都要小心操作的顺序问题。每次调用时,locals()将会接受局部变量的当前值,然后覆盖字典中的对应条目。请看以下示例:
执行结果如下
注意最后对locals()的调用是如何导致x被覆盖的。
除了使用locals()之外,另一种可选的方式是自己创建字典并传递给exec()。示例如下:
最后的运行结果为14
对于大部分针对exec()的应用,这就够了。我们需要确保exec()中访问的变量在全局和局部字典中经过你恰当的初始化。
最后提示:
在使用exec()时,想一想其他的可选方案,就像讨论一开始列出的类似选项
>>>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()时,想一想其他的可选方案,就像讨论一开始列出的类似选项
相关文章推荐
- 在Linux中#!/usr/bin/python之后把后面的代码当成程序来执行。 但是在windows中用IDLE编程的话#后面的都是注释,之后的代码都被当成文本了。 该怎么样才能解决这个问题呢?
- 【转载】用PyInstaller把Python代码打包成单个独立的exe可执行文件
- 不懂编程金融狗的葵花宝典03(python/K近邻法下篇/机器学习入门简单详细代码)
- 详解Python中代码缩进(Indent):影响代码的内在逻辑关系和执行结果
- python编程练习---一行代码实现计算器功能
- 编程之美,剑指offer,以及微软100题的python代码
- python调用HTMLTestRunner+unittest实现一次执行多个测试类,并生成与每个测试类对应的测试报告,并不像某些人写的每次只执行一个测试类,具体看代码,附上整个project代码
- 资源 | 想用Python学机器学习?Google大神替你写好了所有的编程示范代码
- Micropython TPYBoard V10X拼插编程实践之定时器 代码不精通?...
- day09_python socket编程之服务端代码
- Python编程使用tkinter模块实现计算器软件完整代码示例
- Linux 下面编程提高代码执行效率的小技巧
- Python tricks(6) -- python代码执行的效率
- python 代码审计-命令执行漏洞(自己编写的代码)
- web测试常用python代码——ssh远程登陆以及命令执行
- ssh批量登录并执行命令的python实现代码
- python 定时执行装饰器代码
- 编程之美3.11扩展问题 简单并带有错误的环形单链表检测代码
- 基于visual c++之windows核心编程代码分析(18)远程代码注入执行
- 你真的了解jQuery的ready函数吗?当 DOM(文档对象模型) 已经加载,就执行ready里的代码。DOM何时加载完毕?jQuery对html局部操作,DOM为什么不重新加载?