Python高级编程——4.生成器和斐波那契(fibonacci)函数

一、创建生成器(以快速生成列表为例)

生成器的本质是节约内存。   

在python2中的xrange和python3中的range实质上就是一个典型的列表生成器。后面均是以python3为例。range快速生成列表的方法:[x for x in range(num)]  /  [x+y for x in range(num)  for y  in  range(num)]等

Python高级编程——4.生成器和斐波那契(fibonacci)函数

创建生成器:将[ ]换成()后,使得列表的结果不会直接全部输出,而是将其转换成列表生成器,通过next方法将结果依次输出,或for循环方法将结果全部输出。这种方法很大程度了节约了内存空间。在res中实质上保存的是一种算法(x for x in range(num)) /    (x+y for x in range(num)  for y  in  range(num))

Python高级编程——4.生成器和斐波那契(fibonacci)函数

二、将函数返回值转换成生成器

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:


定义一个斐波那契函数:

def  fibonacci (max):
     first,second,n = 0,1,0
     while n<max:
         first,second=second,first+second
         n += 1
         print(second)
运行结果为:1,2,3,5,8,13,21,34,55,89

但是若数值较大,则打印比较缓慢,且比较占用内存,在命令行输入后如下图:
②为了解决打印缓慢的问题,可在函数中增加一个全局变量list=[],但是毫无疑问,这是非常占用内存空间的,请看下面的实例:
Python高级编程——4.生成器和斐波那契(fibonacci)函数

这种方法使得输出结果以列表的显示,解决了输出问题,但是依然还是很占用内存空间
③利用yield关键字,yield关键字加在返回值前,将函数的返回值转换成生成器,使得结果依次输出

Python高级编程——4.生成器和斐波那契(fibonacci)函数

一般调用next()方法,在python2 中使用 .__next__()方法,在python3中两种方法都可以使用。但是field是怎样将函数转换成生成器的呢?其实在函数的返回值前增加field关键字之后,在调用函数时,这个函数并没有运行,只有在调用next方法时,函数才会运行,且运行至field终止,第二次调用next方法时,函数从field之后开始执行,为了更清楚地了解field加入后,函数的运行状况,在field second之前增加一行代码:
print("yield 之前")
在field second之后增加一行代码:
print("yield 之后")
运行代码发生如下结果:
Python高级编程——4.生成器和斐波那契(fibonacci)函数
以上例子充分说明,在第一次调用next(res)方法时,函数运行至yield second终止,再一次调用next()方法时,函数接着yield之后运行。
res为迭代器即generator。
④send关键字在field所在函数中的作用
看以下函数代码,增加一个变量temp,temp=yield即为其赋值为None,运行结果如下:


此时若执行res.send( ),在括号中给值,这个值就会反向传给temp变量,如下图:

以上例子很好的解释了send在函数转换生成器中的作用,可以反向赋值给函数体的变量,借此改变函数中代码运行顺序。
应用场景如:
def    demo(  )  :
        while True:
            print("*"*50)
           temp = yield
          if temp==1:
                print("增加一个用户")
          elif temp==2:
                print("修改用户")
          elif temp ==3:
                print("删除用户")
        print(temp)
        print("~"*50)



实现多任务

模拟多任务(进程,线程,协程)实现方式之一:协程,使得多个任务看似同时进行

import   time
def   test1  ( ):
    while True:
        print("明明")
        yield 0

def   test2  ( ):
    while True:
        print("花花")
        yield 0

while True:
    res1=test1( )
    res2=test2( )
    next(res1)
    next((res2))
    time.sleep(2)

以上代码运行就出现以下结果
明明
花花
明明
花花
明明
花花
明明
花花
明明
花花

“明明”和“花花”几乎同时出现,停顿2s后继续同时出现,这就是field的多任务应用。




总结

生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。

生成器不仅记住了它数据状态;生成器还记住了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

生成器的特点:

1. 节约内存

2. 迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的