python 迭代器和生成器 学习

##列表生成式  能灵活的生成所需列表
temp_list=[i*2 for  i in range(1,11)]
#print(temp_list)

##上面的列表生成式,就是使代码更简洁
a=[]
for i in range(1,11):
    a.append(i)
#print(a)

###迭代器&生成器
'''
经过列表生成式,建立一个列表时,当数据量较大时,不只占用不少的存储空间,若是咱们仅须要访问几个元素,那其余空间就白白浪费了。
若是能够按指定算法推算出要访问的元素,即便用时,才开辟空间,这种一边循环一边计算的机制,称为‘生成器’ generator
'''
#一、用列表做为生成器
temp_list=[i*2 for  i in range(1,11)]
#print(temp_list)                        #已经准备好了每一个元素 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
temp_gen=(i*2 for  i in range(1,11))
#print(temp_gen)
#  运行结果<generator object <genexpr> at 0x03593570>,没有准备每一个元素,须要经过_next_()
#因此生成器不能像list同样,使用切片的方式访问
for i in temp_gen:
    #print(i)
    pass
#在建立一个生成器后,基本上不会调用_next_()访问,而是经过for循环来迭代它,且不关心stopIteration的错误。
# 二、用函数来指定生成器的规则
# 我写的斐波拉契数列:除第一个和第二个数外,任意一个数均可由前两个数相加获得
i=1
bef=0
fibo=[]
while i<20:
    if len(fibo)<2:
        fibo.append(i)
        bef = i
    else:
        bef=fibo[-2]+bef
        fibo.append(bef)
    i=i+1
#print(fibo)
#大神写的 [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
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(20))

''' 这里赋值以前,先计算右边的值,因此赋值前a=1,b=2 ,计算完后a,b=(2,1+2) 因此a=2 b=3
>>> a,b=1,2
>>> t=(b,a+b)
>>> t[0]
2
>>> t[1]
3
>>> a,b=(b,a+b)
>>> a
2
>>> b
3
'''
#要想该函数做为生成器,将print(b) 修改成yield b
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
print(fib(20)) #运行结果<generator object fib at 0x00AF37B0>  
#函数加yield后,再也不是函数了,是生成器了,return的值,在捕获异常时使用,以下:

#死循环一直调用next,会超出生成器的范围
#while True:
#    print(g.__next__()) #StopIteration: done 抛出异常了,捕获它

while True:
    try:
        print(g.__next__())
    except    StopIteration as e:
        print('Generator return value:',e.value)
        break                                                                                                                                                                                                                                            
#函数使用yield,当访问生成器g时,去执行函数fib(),执行到yield时,函数就暂停,再次调用fib()函数时,又接着执行yield后面的,并执行到yield的位置
#即yield一个值后,函数暂停,再次访问生成器时,再规则生产规则yield一个值。
#调用fib(),保存了中断前的状态。

使用生成器,在单线程设备中实现‘多线程’运行算法

#实现串行
#定义生成器
def get_generator():
    for seed in range(1,11):
        yield  seed;
#使用生成器的数据
def worker(seed):
    return seed*seed
#for i in get_generator():#实现了串行任务,我一个数据你使用了,我再产生一个数据你才能使用
#    print(worker(i))
#进一步,可将其抽象为下面的函数:
def serial_yield(generator,worker):
    for seed in generator():
        yield  worker(seed)  #又申明一个生成器

做业,写一个包包子的任务,包10个包子,把任务分红几块,分工串行(分擀面皮、包包子,包完一个计算一个。)使用生成器,实现并行多线程

 

def  ganmianpi():
    while True:
        yield  '面皮擀好啦,接着!'
def baobaozi():
    n=1
    while n<11:
        print(ganmianpi().__next__())
        yield  '包完第%s个包子'%n
        n=n+1
for baozi in baobaozi():
    print(baozi)

用生成器实现并行(协调式)app

import  time
def consumer(name):
    print('%s 准备吃包子啦!'%name)
    while True:
        baozi=yield

        print('包子<%s>来了,被<%s>吃了! '%(baozi,name))
def producter(name):
    c=consumer(name)#这里是申明变量c ,是生成器,不是执行函数,调试时不会进入迭代器内部
    c.__next__()#访问生成器的元素,才会去迭代器内部看生成规则
    print('老子开始准备包包子啦!')

    for i in range(1,6):
        time.sleep(1)
        print('作了%s个包子!'%i)
        c.send(i)

producter('weii')#这里是调用函数哦

 上面的任务其实仍是串行的,只是看到多个不一样的任务在同时进行,任务在不一样的交替,看起来像并行。函数

 直接调用consumer该生成器,yield无对应值,返回为None,那这样给yield传值呢spa

c=consumer('Chenweiei')
c.__next__()
c.__next__() #_next_必需要加() 才能访问到元素
'''Chenweiei 准备吃包子啦!
包子<None>来了,被<Chenweiei>吃了! 
'''
c.send('白菜馅的') #唤醒当前的生成器,并赋值给yield,继续往下走,c.__next__() 是只唤醒
'''Chenweiei 准备吃包子啦!
包子<白菜馅的>来了,被<Chenweiei>吃了! 
'''
from collections import  Iterator
print(isinstance([],Iterator)) #False 判断对象是否为迭代器
print(isinstance(c,Iterator)) #True--------------------------------
#可迭代对象(可循环的对象) charpter【13】
#迭代器:可用next()函数调用,并不断返回下一个值的对象,在可迭代对象上又加了条件

从上面截图,能够看到列表就没有next() 函数线程

相关文章
相关标签/搜索