本节介绍一些之前语法的高级使用,可以是我们的程序看起来更为优雅和高效。

 

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

更多文章,请关注:
Python自学笔记-第8章高级程序设计技术(1)-LMLPHP           

04-25 06:06