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方法)的更多相关文章

  1. python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法

    一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstan ...

  2. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  3. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  4. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

  5. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  6. Python全栈开发【基础二】

    Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...

  7. python全栈开发中级班全程笔记(第二模块、第四章)(常用模块导入)

    python全栈开发笔记第二模块 第四章 :常用模块(第二部分)     一.os 模块的 详解 1.os.getcwd()    :得到当前工作目录,即当前python解释器所在目录路径 impor ...

  8. 学习笔记之Python全栈开发/人工智能公开课_腾讯课堂

    Python全栈开发/人工智能公开课_腾讯课堂 https://ke.qq.com/course/190378 https://github.com/haoran119/ke.qq.com.pytho ...

  9. 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  可迭代的 可迭 ...

随机推荐

  1. 01:MongoDB基础

    1.1 MongoDB简介 1.特点 1. MongoDB的提供了一个面向文档存储,操作起来比较简单和容易. 2. 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName=" ...

  2. linux 文件同步

    ref: https://www.cnblogs.com/MacoLee/p/5633650.html https://wenda.so.com/q/1505308236213470 http://b ...

  3. git博客好的例子

    01: https://github.com/Gaohaoyang/gaohaoyang.github.io 02: https://gaohaoyang.github.io/2018/06/01/a ...

  4. UVa 11997 K Smallest Sums - 优先队列

    题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和. 考虑将前i个数组合并,保留前k个和.然后考虑将第(i + 1)个数组和它合并,保留前 ...

  5. Codeforces 700B Connecting Universities - 贪心

    Treeland is a country in which there are n towns connected by n - 1 two-way road such that it's poss ...

  6. Apache下的ArrayUtils工具类总结

    ArrayUtils中的方法: 1.add():将给定的数据添加到指定的数组中,返回一个新的数组. 2.addAll():合并两个数组. 3.contains():检查该数据在该数组中是否存在,返回一 ...

  7. Bootstrap3基础 form-horizontal 表单元素横向布局 简单示例

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  8. Python3 tkinter基础 Button command 单击按钮 在console中打印文本

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  9. Golang中使用kafka

    golang中比较好用的kafka client有 sarama confluent-kafka-go go_kafka_client optiopay-kafka siesta 其中 sarama的 ...

  10. (转)Nginx学习

    (二期)15.负载均衡nginx [课程15]nginx安装.xmind0.2MB [课程15]Nginx能做什么.xmind0.1MB [课程15]负载均衡nginx.xmind96.7KB [课程 ...