什么是生成器:
通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator。
生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器。
创建列表,直接在内存生成,不管调不调用,都占用内存空间。而创建生成器,只有调用时,才会在内存生成。
列表和生成器的区别在于最外层,最外层为[]时为列表,最外层为()时为生成器generator
列表如下>>>[i*2 for i in range(10)][0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
生成器generator如下
>>>(i*2 for i in range(10))
<generator object <genexpr> at 0x02E9D2A0>
生成器不能支持如同列表调用数据的方式,如列表的切片,如果想要调用,方式有通过for循环,一个一个去调用,调用那次就产生那次数据。
生成器只记住当前位置,通过__next__()方法获取下一个位置的值,不能往后退,不能跳,只能一个一个去取。
生成器虽然非常强大,但是如果算法的推算非常复杂,用列表生成式的for循环无法生成的时候,可以用函数的方式实现。
例如斐波那契数用列表生成式是写不出来的,但是用函数写就简单很多了。
斐波那契数:当前数值等于前面两个数值相加。
def fib(max): n,a,b=0,0,1 while n <max: yeild b a,b=b,a+b n+=1
f=fib(100)
print(f.__next__())#通过调用next方法,调用一次就生成一次数据
生成器除了可以节省内存外,还可通过yield实现在单线程情况下实现并发运算
1 # Author : 梁观康 2 3 4 # 顾客和营业者的关系 5 6 import time 7 8 def Consumer(name):#顾客函数 9 print('%s has started to eat the steamed stuffed bun!'%name) 10 while True: 11 class = yield 12 print('The %s is coming,but eaten by %s!'%(class,name)) 13 14 def Producer(name):#营业者函数 15 C1 = Consumer('Luna')#生成对象 16 C2 = Consumer('Iriving')#生成对象 17 C1.__next__()#调用对象 18 C2.__next__()#调用对象 19 print('LGK is starting to make the steamed stuff bun!!') 20 for i in range(10):#循环10次 21 time.sleep(1)#休眠1秒 22 kind = ['肉包','菜包'] 23 print('LGK has made two buns, the first one is %s,the second one is %s'%('肉包','菜包')) 24 C1.send(kind[0])#给yield赋值 25 C2.send(kind[1])#给yield赋值 26 27 28 Producer('LGK')
转载于:https://www.cnblogs.com/lianggk/p/11506734.html