Python全栈开发-执行字符串形式的语句和字符串形式的表达式方法(即exec和eval方法)
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 可迭代的 可迭 ...
随机推荐
- java常用代码段整理(持续更新)
FileWriter指定编码格式 FileWriter 默认是用(ISO-8859-1 or US-ASCII)西方编码的,总之不是UTF-8的,而FileWriter类有getEncoding方法, ...
- MyBatis 与 Hibernate 到底哪个更快?
前言 由于编程思想与数据库的设计模式不同,生出了一些ORM框架. 核心都是将关系型数据库和数据转成对象型.当前流行的方案有Hibernate与myBatis. 两者各有优劣.竞争激烈,其中一个比较重要 ...
- Microsoft Visual Studio 2010(vs10)安装与使用
安装1.下载软件: 云盘分享http://pan.baidu.com/s/1i4JL9GT 2.安装 打开Microsoft Visual Studio 2010目录,双击setup.exe ,运行 ...
- 【python003-变量】
变量 一.在使用变量之前,需要先对其进行赋值 二.变量命名的规则:可以包含字母,数字,下划线,但是不能以数字开头 三.字符串: 1.引号内的一切东西 2.python的字符串是要在两边加上引号,对于单 ...
- SpringBoot 解决HttpServletRequest只能读取一次
业务逻辑,通过filter读取请求的request,获取token,并将token传递后面流程使用 BodyReaderHttpServletRequestWrapper: public class ...
- <Python>判断变量是否是DataFrame 或者 Series
https://stackoverflow.com/questions/14808945/check-if-variable-is-dataframe Use the built-in isinsta ...
- 【做题】sgu189 Perl-like Substr——dark模拟
注:这篇博客纯属为凑篇数而生. 题面较长,幸运的是,网上给出了相当不错的翻译. 需要支持的操作很简单,即对子串提取.赋值和输出,且对时间复杂度没有要求.换言之此题有成为块链毒瘤题的潜质.难点在于输入的 ...
- 论文笔记:Capsules for Object Segmentation
Capsules for Object Segmentation 2018-04-16 21:49:14 Introduction: ----
- [js] - js中类(伪)数组装正规数组
今天的js中使用了自定义的原型方法去重后,再调用这个获取的去重的数组传入另一个含有for循环的方法时, console.log出错: dimensions:createTime,华联石化,海油石化,青 ...
- 小文笔记 - phantomjs
小文笔记 - phantomjs 视频推荐: http://www.intalesson.com/compedium/phantom 2017-05-13 第一节:安装 Windows安装: 下载解压 ...