列表生成式
现在有个需求,看列表[0,1,2,3,4,5,6,7,8,9],要求你把列表里的每个值加1,怎么实现?
a = [i+1 for i in range(10)]
这样的写法就叫做列表生成式
生成器
通过列表生成式,我们可以直接创建一个列表。但是,收到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间就白白浪费了。
所以,如果列表元素可以按某种算法推算出来,那我们是否可以在循环的过程不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在python中,这种一边循环一边计算的机制,称为生成器:generator:
要创建一个generator,有很多种方法,第一种方法很简单,只要把一个列表生成式的[]改成()就创建了一个genarator
a = (x if x<5 else x*x for x in range(10)) print(a)
print(next(a))
print(next(a))
print(next(a))
<generator object <genexpr> at 0x01304870>
0
1
2
>>> a3 =(i for i in range(5)) >>> a3 <generator object <genexpr> at 0x003C48F0> >>> next(a3) 0 >>> next(a3) 1 >>> next(a3) 2 >>> next(a3) 3 >>> next(a3) 4 >>> next(a3) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
generator保存的是算法,每次调用next(a)就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
当然,上面这种不断调用next()的方法太麻烦了,正确的方法是使用for循环,因为generator也是可迭代对象:
a = (i for i in range(10)) for i in a: print(i)
0
1
2
3
4
5
6
7
8
9
所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代他,并且不需要关心StopIteration的错误。
generator非常强大.如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数。
斐波那契:
斐波那契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(max): n,a,b = 0,0,1 while n<max: yield b #把函数的执行过程冻结到这一步,并且把b的值返回给外部 a,b = b,a+b n= n+1 return(‘done‘) print(fib(5)) for i in fib(5): print(i)
yield vs return
return 返回并终止function
yield返回数据,并冻结当前的执行过程
next 唤醒冻结的函数执行过程,继续执行,直到遇到下一个yield
函数有了yield之后:
1.函数名加()就得到了一个生成器
2.return在生成器里代表函数的终止,并会报错
生成器的send方法
def range2(n): count = 0 while count < n: print(‘count‘,count) count += 1 sign =yield count print(‘---sign‘,sign) if sign == ‘stop‘: break return 3333 new_range = range2(6) n1 = next(new_range) n2 = next(new_range) n3 = next(new_range) n4 = next(new_range) new_range.send(‘stop‘) #send的作用,1唤醒并继续执行 #2.发送一个信息到生成器
原文:https://www.cnblogs.com/echo-kid-coding/p/11327976.html