python 基础 day04—列表生成器/生成器

列表生成式

a=[i*2 for i in range(10)]
print(a)
#==> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

若不用列表生成式,可用以下方法达到以上效果

for i in range(10):
    a.append(i*2)

print(a)

比较复杂!

 

生成器

1.只有在调用时才会生成相应的数据

2.只记录当前位置

3.只有一个__next__方法

创建一个生成器,只要把一个列表生成式的[]改成(),就创建了一个generator

( i*2 for i in range(10) )

 

现在,用函数写斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到

def fib(max):
    n,a,b=0,0,1
    while n < max:
        print(b)
        a,b=b,a+b
        n=n+1
    return 'done' #出现异常的时候打印的消息

print(fib(10))

结果:
1
1
2
3
5
8
13
21
34
55
done #所有消息均输出完毕,因此抛出异常消息 

可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

要把fib函数变成generator,只需要把print(b)改为yield b就可以了

通过函数做成一个生成器

def fib(max):
    n,a,b=0,0,1
    while n < max:
        yield(b)   #yield的作用是保存当前状态,然后返回
        a,b=b,a+b
        n=n+1
    return 'done'

f= fib(10)
print(a)

print(f.__next__())  #输出f当前值
print(f.__next__())
print("休息一下")
print(f.__next__())
print(f.__next__())

print("===从这里开始for循环==")
for i in f:
    print(i)

结果:

<generator object fib at 0x03671230>
1
1
休息一下
2
3
===从这里开始for循环==
5
8
13
21
34
55

  最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

 

 下面我们尝试通过生成器实现协程并行运算

先来个前奏

def consumer(name):
    print("%s 准备吃包子!" %name)
    while True:
        baozi=yield  #程序走到yield然后返回
        print("包子[%s]来了,被[%s]吃了!"%(baozi,name))

c=consumer("Cherry")
c.__next__() #调用生成器
c.__next__()

结果:
Cherry 准备吃包子!
包子[None]来了,被[Cherry]吃了! #因为没有包子,所以显示none

因此,我们给做个包子

def consumer(name):
    print("%s 准备吃包子!" %name)
    while True:
        baozi=yield  #yield作用是保持当前状态然后返回,直到下次执行时从这里继续执行
        print("包子[%s]来了,被[%s]吃了!"%(baozi,name))

c=consumer("Cherry")
c.__next__() #调用生成器
baozi1="荠菜猪肉馅"
a.send(baozi1) #send给yield赋值,然后yield传值给baozi

结果:
Cherry 准备吃包子!
包子[荠菜猪肉馅]来了,被[Cherry]吃了!

完整的正餐!

#_*_coding:utf-8_*_

import time
def consumer(name):
    print("%s 准备吃包子!" %name)
    while True:
        baozi=yield
        print("包子[%s]来了,被[%s]吃了!"%(baozi,name))


def producer(name):
    c=consumer('A')     #c是name为A的一个生成器
    c2=consumer('B')    #c2是name为A的一个生成器
    c.__next__()        #执行c的第一步操作
    c2.__next__()       #执行c2的第一步操作
    print("开始做包子!")
    for i in range(3):
        time.sleep(2)
        print("做了两个包子")
        c.send(i)       #执行c的下一步操作,把i传值给yield 
        c2.send(i)

producer("Cherry")



结果:
A 准备吃包子!
B 准备吃包子!
开始做包子!
做了两个包子
包子[0]来了,被[A]吃了!
包子[0]来了,被[B]吃了!
做了两个包子
包子[1]来了,被[A]吃了!
包子[1]来了,被[B]吃了!
做了两个包子
包子[2]来了,被[A]吃了!
包子[2]来了,被[B]吃了!
完整版

 

 

 

posted @ 2019-01-15 15:09  cherry_cui  阅读(178)  评论(0编辑  收藏  举报