##列表生成式 能灵活的生成所需列表 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() 函数线程