列表生成式,一般的我们想把对一个列表的函数进行操作,一般是用循环进行调用。
例如我们想将0-9的元素乘以2,一般来讲:
for i in range(10):
print(i*2)
而我们使用列表生成式的话,直接可以写作
list=[ i*2 for i in range(10)]
直接打印即可,得到一个列表,这样简洁了很多,同时不需要循环引入
列表生成式,在面对大数据量的时候,不会直接占用那么大的内存,它
只是引入了一个算法,只有在调用到列表的这个元素时,它才会生成这个元素,若一个100w元素的列表,传统的调用方式,会首先分配部分内存给这100w个元素,但若使用列表生成式,只有开始调用时,才会占用内存空间。
而生成器简单来讲,就是将列表生成式外卖呢的[]转换成()
list=(i*2 for i in range(10)]
print(type(list))
output:
<class 'generator'>
生成器只有一种方法,就是next方法,调用方式为:
f=(i*i for i in range(5) )
print(f.__next__())
print(f.__next__())
生成器只能记录当前的位置,不计前后,没有上一个这种方法
如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现
实现斐波那契数列
def fib(max):
n,a,b =0,0,1
while n < max:
print(b)
a,b = b,a+b
n = n+1
return 'done'
fib(6)
这里需要注意的一点,最关键一点为a,b=b,a+b,
如果顺序执行的方式去执行
a=b
b=a+b
则循环输出结果为:1,2,3,6.....违背了数列的规律
实际上应该理解为:
t=(b,a+b)
a=t[0]
b=t[1]
输出为:1,1,2,3,5,8
而我们这里可以引入生成器,只需将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'
同时调用时可以查看fib(6)的类型,可以看到为
<class 'generator'>
若要调用生成器还是需要使用next方法
print(f.next())
将6个值都取到则需要调用6次next方法
但当调用第7次时,程序会报错,抛出“StopIteration”的异常
因此我们可以改写调用函数:
def fib(max):
n,a,b =0,0,1
while n < max:
yield b
a,b = b,a+b
n = n+1
return 'done'
f=fib(10)
while True:
try:
x = next(f)
print('f:',x)
except StopIteration as e:
print('Generator return value:',e.value)
break
while 循环中的next函数实际作用与内置函数f.next()一致
通过异常判断来修正程序,不会出现报错的情况,同时中断程序
另外我们可以使用生成器来写一个简单的生产者消费者模型
def consumer(name):
print("%s 准备吃包子了!" %name)
while True:
baozi=yield
print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
c=consumer('carl')
c.__next__()
c.send("韭菜馅")
我们看到这里将生成器赋值给“baozi”,这里的生成器就是保存状态,next是唤醒这个生成器,而用send方法是给生成器传值,而consumer是消费者,吃包子的
next方法与send方法都可以调用生成器,但不同的是next方法是调用生成器的值,而send方法则是向生成器传值
而consumer是吃包子的,send值则代表生产包子
完整的做包子,吃包子模型:
import time
def consumer(name):
print("%s 准备吃包子啦!" % name)
while True:
baozi = yield ##将生成器赋值给包子
print("包子[%s]来了,被[%s]吃了!" % (baozi, name))
c=consumer('cris')
def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("%s开始准备做包子啦!" %name)
for i in range(1,10):
time.sleep(1)
print("做了%s个包子!" %i)
c.send(i)
c2.send(i)
producer("cris")
网友评论