本节介绍一些之前语法的高级使用,可以是我们的程序看起来更为优雅和高效。
1.过程性程序设计
1.1.使用字典进行分支
如果遇到大量含有if和elif的分支判断中,按照传统的写法无疑会降低程序逻辑的可读性,此时可以使用字典方式替换if else的使用。
以下示例进行说明:
In [3]:
a = 10 b = 8 strs = input("输入你的操作:") if strs == '+': print(a+b) elif strs == '-': print(a-b) elif strs == '*': print(a*b) else: print(a/b)
输入你的操作:+ 18
可以转化为:
In [4]:
a = 10 b = 8 strs = input("输入你的操作:") actions = {'+':a+b,'-':a-b,'*':a*b,'/':a/b} print(actions[strs])
输入你的操作:+ 18
1.2.生成器表达式与函数
生成器提供了一种执行“惰性”评估的方法,意味着只有在实际需要的时候才计算值,这比一次性计算一个很大的列表要更加有效。有效的生成器可以生成我们所需要数量的值--而没有上限
- 生成器表达式的语法如下:
(expression for item in iterable) (expression for item in iterable if condition)
In [5]:
for t in (x for x in range(10) if x%2==0): print(t)
0 2 4 6 8
- 生成器函数的语法如下:
In [11]:
def getNum(num=1): num = 1 while True: yield num num +=1
In [12]:
getNum()
Out[12]:
<generator object getNum at 0x00000214B6597D58>
In [13]:
for t in getNum(): if t > 5: break print(t)
1 2 3 4 5
- 使用send方法改进的生成器函数为:
In [16]:
def getNum1(num=1): num = 1 while True: recived = yield num if recived is None: num += 1 else: num = recived + 10
In [17]:
result = [] cnum = getNum1(2) while len(result)<5: x = next(cnum) if x==4: x = cnum.send(7) result.append(x)
In [18]:
print(result)
[1, 2, 3, 17, 18]
1.3.动态代码执行与动态导入
动态代码执行即是让用户自己输入代码并让Python执行,此种方法即允许Python程序执行任意代码必然会带来很大的安全风险,故而需要谨慎使用。
另外通过动态执行,可以为程序增加和扩展动态功能。
1.3.1.eval()函数
计算指定表达式的值。也就是说它要执行的python代码只能是单个表达式(注意eval不支持任何形式的赋值操作),而不能是复杂的代码逻辑。其语法格式如下:
eval(source, globals=None, locals=None)
参数说明:
- source:必选参数,可以是字符串,也可以是一个任意的code(代码)对象实例(可以通过complie函数创建)。如果它是一个字符串,它会被当作一个(使用globals和locals参数作为全局和本地命名空间的)python表达式进行分析和解释。
- globals:可选参数,表示全局命名空间(存放全局变量),如果被提供,则必须是一个字典对象。
- locals:可选参数,表示全局命名空间(存放局部变量),如果被提供,可以是任何映射对象。如果参数被忽略,那么它将会取与globals相同的值。 如果globals与locals都被忽略,那么它们将取eval()函数被调用环境下的全局命名空间和局部命名空间。
返回值:
- 如果source是一个code对象,且创建该code对象时,complie函数的mode参数是‘exec’,那么eval()函数的返回值是None;
- 否则,如果source是一个输出语句,如print(),则eval()返回结果为None;
- 否则,source表达式的结果就是eval()函数的返回值
In [23]:
eval(input('请您输入要执行的脚本:'))
请您输入要执行的脚本:print([x for x in range(5)]) [0, 1, 2, 3, 4]
1.3.2.exec()函数
动态执行python代码。也就是说exec可以执行复杂的python代码,而不像eval函数那样只能计算一个表达式的值。
exec(source, globals=None, locals=None)
参数说明:
- source:必选参数,表示需要被指定的python代码。它必须是字符串或code对象。如果source是一个字符串,该字符串会先被解析为一组python语句,然后执行。如果source是一个code对象,那么它只是被简单的执行。
- globals:可选参数,这个参数管控的是一个全局的命名空间,即 expression 可以使用全局命名空间中的函数。如果只是提供了 globals 参数,而没有提供自定义的
__builtins__
,则系统会将当前环境中的__builtins__
复制到自己提供的 globals 中,然后才会进行计算;如果连 globals 这个参数都没有被提供,则使用 Python 的全局命名空间。 - locals:可选参数,这个参数管控的是一个局部的命名空间,和 globals 类似,当它和 globals 中有重复或冲突时,以 locals 的为准。如果 locals 没有被提供,则默认为 globals。
返回值:
- exec函数的返回值永远为None。
In [27]:
import math code = """ def area_of_sphere(r): print(4*math.pi*r**2) """ context = {} context['math']=math exec(code,context)
In [28]:
area_of_sphere = context['area_of_sphere'] area_of_sphere(5)
314.1592653589793
globals参数即可作为exec执行函数中需要获取参数或模块的来源(如:math),也可以作为外部想获取exec执行函数的字典(如:area_of_sphere)
1.3.3.complie()函数
compile() 函数将一个字符串编译为字节代码。其语法格式
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
参数说明:
- source:字符串或AST对象,表示需要进行编译的python代码
- filename:指定需要编译的代码文件,如果不是文件读取代码则传递一些可辨认的值。
- mode:用于标识必须当做那类代表来编译;如果source是由一个代码语句序列组成,则指定mode=‘exec’,如果source由单个表达式组成,则指定mode=‘eval’;如果source是由一个单独的交互式语句组成,则指定modo=‘single’。必须要制定,不然肯定会报错。
In [46]:
code = """ import math def area_of_sphere(r): print(4*math.pi*r**2) """ c = compile(code,'','exec') c
Out[46]:
<code object <module> at 0x00000214B6662C90, file "", line 2>
In [50]:
context = {} exec(c,context) context['area_of_sphere'](5)
314.1592653589793
In [51]:
exec(c) c1 = globals()['area_of_sphere'] c1(5)
314.1592653589793
更多文章,请关注: