1.推导器的弊端
受内存限制,列表容量 有限
而且,创建一个包含100万元素的列表,却只是用其中某几个,
浪费空间。
所以 如果列表元素可以按照某算法推算出来,在后续使用中不断推算,
边循环,边计算 --> 生成器 generator
2.生成器和生成器的使用
1.列表生成器的创建
# 1 列表推导式 --> 列表生成器
# [0,3,6,9,12,15,18,21,....,27]
nl_1 = [x * 3 for x in range(20)]
print(type(nl_1)) # <class 'list'>
# 生成器:
gl_1 = (x * 3 for x in range(7))
print(type(gl_1)) # <class 'generator'>
1.列表生成器的使用
# 使用方法一
print(gl_1.__next__())
# 使用方法二
print(next(gl_1))
# StopIteration 超出 则 抛出 异常
while True:
try:
g = next(gl_1)
except Exception as e:
print(e)
break
else:
print(g)
2.借助函数完成
只要函数中出现yield关键字,说明函数就不是函数了,变成生成器了,yield相当于return 变量,在暂停
步骤:
1.定义一个函数,函数中使用yield关键字
2.调用函数,接收调用的结果
3.得到的结果就是生成器
4.借助于next(),next()
# yield 关键字
def func():
n = 0
while True:
n += 1
yield n
g = func()
print(g)
print(next(g))
3.generator.send()
既可以接收数据,也可以往里面传值。
注意:第一次调用send(None) 因为先执行send,还没有进入函数,就传值不合理
def gen():
i = 0
while i < 5:
temp = yield i
print('temp ', temp)
i += 1
return None
g=gen()
g0 = g.send(None)
print(g0)
g1 = g.send('呵呵')
print(g1)
g2 = g.send('oo')
print(g2)
进程>线程>协程
一个线程下有多个协程
def task_1(n):
for i in range(n):
print('Doing task 1, coding ', i)
yield None # 增加yield 利用其 暂停功能
def task_2(n):
for i in range(n):
print('我正在做第二个任务,现在是 ', i)
yield
# 任务1、2 交替运行
g1 = task_1(8)
g2 = task_2(5)
while True:
try:
next(g1)
g2.__next__()
except:
break
生成器 generator
列表生成式 产生
g = (x for x in range(20))
函数 yield
产生元素
next(generator)
generator.next()
generator.send(xx)
应用:协程 --> 提高效率