Python有时需要动态的创造Python代码,然后将其作为语句执行 或 作为表达式计算。
exec用于执行存储在字符串中的Python代码。
1、 语句与表达式的区别:表达式是 某事,语句是 做某事(即告诉计算机做什么)。
比如2*2是4,而print 2*2是打印4。上述两句代码在交互式解释器中执行的结果是一样的,是因为解释器总是把所有表达式的值打印出来而已。而在程序中编写类似2*2这样的表达式并不会打印显示什么,编写print 2*2则会打印4。
语句与表达式的区别在赋值时更明显,因为语句不是表达式,所以没有值。如在交互式解释器中输入 x=2则不会打印任何东西,立刻出现新的提示符。虽然什么也没显现,但是有些东西已经发生变化如x的值现在变为3.这也是语句特性的一般定义:它们改变了事物。比如,赋值语句改变了变量,print语句改变了屏幕显示的内容。
2、 命名空间(作用域) 全局变量和局部变量
除了全局作用域外,每个函数会都会创建一个新的作用域。变量分为全局变量和局部变量,函数内的变量称为局部变量只在局部命名空间中起作用。
在函数内部读取全局变量一般来说不是问题,直接访问即可。但是,如果局部变量名或者参数的名字与全局变量名相同的话,就不能直接访问了,因为全局变量被局部变量给屏蔽了。如果确实需要的话,可以使用globals函数获取被屏蔽的全局变量值。(globals返回全局变量的字典,locals返回局部变量的值)。例如:有一个名为parameter的全局变量,那么在combine(parameter)函数内部访问全局变量时,因为与参数重名,必须使用globals()['parameter']获取。代码如下:
def combine(parameter):
print parameter+globals()['parameter'] #函数调用
parameter="hello"
combine("berry")
上面讲的是再函数内部读取全局变量的方法,不包括修改。如果要在函数内部修改全局变量,需要告知修改的值是全局变量,因为在函数内部将值赋予一个变量那么变量自动成为局部变量。通过global关键字来告诉Python函数内一个需要修改的变量是一个全局变量。代码如下:
x=1
def change_global(n):
global x
x=x+1
3、执行字符串的语句 exec
如输入exec "print 'hello'"会打印出hello。(注意:Python 3.0中,exec是一个函数不是一个语句了,因此使用exec('字符串语句')的方式来调用)。exec执行字符串语句存在安全风险,因为exec可能会干扰命名空间,即改变不应该变的变量。例如:
从上面的例子可以看出,exec干扰了命名空间,改变了sqrt的值,使其不是一个函数而变成1了。由此可见,如果对exec不加限制就会存在安全风险。下面是改进措施。
措施:通过增加 in <scope>来实现,其中的<scope>是一个字典,该字典起到放置代码字符串命名空间的作用。这样exec执行的代码只会在<scope>代表的命名空间中起作用。如:
从上面代码中可以看到,exec语句在scope命名空间中执行,不会影响到现在命名空间的sqrt。scope虽然充当命名空间的作用,但实质仍是一个字典,所以如果想知道scope命名空间中有多少变量时,可通过len(scope)获得,可通过scope.key()获得scope命名空间的所有变量。
4、eval 会计算字符串形式的Python表达式,并返回结果的值。
exec语句不会返回任何对象。而eval会返回表达式的值。下面的代码可以创建一个Python计算器:
#Python计算器
print eval(raw_input("Please input an arithmetic expression:"))
上面代码解释,上面代码中eval内部现在还不是字符串,首先执行raw_input()函数,raw_input()返回你输入的求值字符串,现在eval函数内部就是求值字符串了,就可以用eval进行字符串的求值了。如输入:4*5+6,那么raw_input就会返回“4*5+6”,eval求值后为26.
要注意上面代码与下面代码的区别:
print eval('raw_input("Please input an arithmetic expression:")')
在这个代码中,与Python计算器代码不同的是,eval函数内直接就是字符串,那么直接对字符串求值,但是字符串中是raw_input表达式,raw_input表达式将用户的输入转换为字符串,所以如果输入4+5的话会返回"4+5"。注意:raw_input('xxxxx')是一个表达式,表达式的值就是用户输入。 可能疑惑的是代码:exec('raw_input("Please input an arithmetic expression:")')不会报错,因为ecec也可以用于表达式,只是什么效果也没达到而已(既不返回值,也没干事情)。
跟exec一样,eval也可以使用命名空间。因为尽管表达式一般不会给变量重新赋值,但是表达式可以通过调用函数来达到给全局变量赋值的目的。例如执行下面代码后,全局变量x的值会被重新赋值为2:
x=1
def inc_x():
global x
x=x+1
eval("inc_x()")
print x
从上面的代码可以看出eval函数也是不安全的,必须使用命名空间。事实上,可以为eval提供两个命名空间,一个是全局的,另一个是局部的。全局的必须是字典,局部的可以是任何形式的映射。
exec和eval的命名空间使用代码(命名空间可以不是空的字典,可以提前为命名空间提供一些值):
scope={}
scope['x']=1
scope['y']=2
print eval('x+y',scope) scope={}
exec "x=2" in scope
eval("x*x",scope)
Python全栈开发-执行字符串形式的语句和字符串形式的表达式方法(即exec和eval方法)的更多相关文章
-
python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法
一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstan ...
-
Python全栈开发【面向对象进阶】
Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...
-
Python全栈开发【面向对象】
Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...
-
Python全栈开发【模块】
Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...
-
Python全栈开发【基础三】
Python全栈开发[基础三] 本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...
-
Python全栈开发【基础二】
Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...
-
python全栈开发中级班全程笔记(第二模块、第四章)(常用模块导入)
python全栈开发笔记第二模块 第四章 :常用模块(第二部分) 一.os 模块的 详解 1.os.getcwd() :得到当前工作目录,即当前python解释器所在目录路径 impor ...
-
学习笔记之Python全栈开发/人工智能公开课_腾讯课堂
Python全栈开发/人工智能公开课_腾讯课堂 https://ke.qq.com/course/190378 https://github.com/haoran119/ke.qq.com.pytho ...
-
python全栈开发从入门到放弃之迭代器生成器
1.python中的for循环 l = [1,2,3,4,5,6] for i in l: #根据索引取值 print(i) 输出结果: 1 2 3 4 5 6 2.iterable 可迭代的 可迭 ...
随机推荐
-
HTML+CSS布局技巧及兼容问题【阅读季】
在IE6和IE7中,行高值必须大于字体的2px以上才能保证字体的完整显示或当作为链接时能显示下划线. IE6 下去掉 input等元素 的边框 border: 0 none; 所有浏览器都可以了 边框 ...
-
Largest palindrome product
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2 ...
-
C高级 服务器内核分析和构建 (一)
引言 最经看cloud wind 的 skynet服务器设计. 觉得特别精妙. 想来个专题先剖析其通信层服务器内核 的设计原理. 最后再优化.本文是这个小专题的第一部分, 重点会讲解对于不同平台通信基 ...
-
Altium Designer 常用快捷键总结
原理图:1:按住shift 拖动某个元件,可快速复制.2:按住鼠标滚轮 鼠标上下滑动 放大缩小.3:按住Ctrl 按住鼠标右键 鼠标上下滑动也放大缩小.4:按住Ctrl 拖动某个元件 可以移动位置 ...
-
Angular 2 前端 http 传输 model 对象及其外键的问题
个人随笔,记录问题及思路草稿,非文章性质. 对于设备编辑场景,需要显示设备类型(外键), 前端有如下 TypeScript model(此 model 和后端实体 model 通常相对应) ...
-
简单的C语言编译器--概述
在学习了编译原理的相关知识后,逐渐的掌握一个编译器的结构.作用和实现方法.同时,希望自己在不断的努力下写出一个简单的C语言编译器. 实现步骤 词法分析器:将C语言测试代码分解成一个一个的词法单元: ...
-
SimpleDateFormat 常用用法
1.SimpleDateFormat函数语法: G 年代标志符 y 年 M 月 d 日 h ...
-
Ubuntu ARM更改为国内源
关键词:ubuntu arm ubuntu-ports 国内源 镜像 阿里源 apt apt-get install update 0%working 速度慢 rk3399 开发板 ...
-
String类源码解析
1. String是使用char[]数组来存储的,并且String值在创建之后就不可以改变了.char[]数组的定义为: /** The value is used for character sto ...
-
Oracle10g 连接 sqlserver 在server2008r2 中连接 iis7 .net4.0
一.做好了连接但是到了64位的server2008r2上就是不行,报错dns上不匹配.最后找到原因了 自己到c盘里面找32位的odbc管理工具然后建立连接,然后一切正常. 二.iis7 .net4.0 ...