2018.8.13 python中生成器和生成器表达式
Posted 中杯可乐不加冰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018.8.13 python中生成器和生成器表达式相关的知识,希望对你有一定的参考价值。
主要内容:
1、生成器和生成器函数
2、列表推导式
一、生成器
生成器是指就是迭代器,在python中有三种方式来获取生成器:
1、通过生成器函数
2、通过各种推导式来实现生成器
3、通过数据的转换也可以获取生成器
yield 和return的区别:
yield分段来执行一个函数,break停止函数执行。
当程序运行完最后一个yield,那么后面继续进行__next__()程序会报错。
send使用方法:send和__next__()一样可以让生成器执行到下一个yield。
def eat():
print(\'我吃什么啊\')
a = yield \'馒头\'
print(\'a = \',a)
b = yield \'大饼\'
print(\'b = \',b)
c = yield \'韭菜盒子\'
print(\'c = \',c)
yield \'GAME OVER\'
gen = eat() #获取生成器
ret1 = gen.__next__()
print(ret1) #结果:我吃什么啊 馒头
ret2 = gen.send(\'胡辣汤\')
print(ret2) #结果:a = 胡辣汤 大饼
ret3 = gen.send(\'狗粮\')
print(ret3) #结果:b = 狗粮 韭菜盒子
ret4 = gen.send(\'猫粮\')
print(ret4) #结果:c = 猫粮 GAME OVER
send 和 __next__()区别:
1、send和 __next__()都是让生成器向下走一次
2、send可以给上一个yield的位置传递值,不能给最后一个yield发送值。在第一次执行生成器的时候不能使用send()。
生成器可以使用for循环来获取内部元素:
def func():
print(111)
yield 222
print(333)
yield 444
print(555)
yield 666
gen = func()
for i in gen:
print(i)
# 结果:
# 111
# 222
# 333
# 444
# 555
# 666
for i in list(gen):
print(i)
# 结果:
# 111
# 222
# 333
# 444
# 555
# 666
二、列表推导式,生成器表达式及其他推导式
首先我们先看一下这样的代码, 给出一个列表, 通过循环, 向列表中添加1-14 :
lst = []
for i in range(1, 15):
lst.append(i)
print(lst)
替换成列表推导式:
lst = [i for i in range(1, 15)]
print(lst)
列表推导式的常用写法:
[ 结果 for 变量 in 可迭代对象 if 条件 ]
生成器表达式和列表推导式的语法基本上是一样的. 只是把[ ]替换成()
# 获取1-100内能被3整除的数
gen = (i for i in range(1,100) if i % 3 == 0)
for num in gen:
print(num)
# 100以内能被3整除的数的平方
gen = (i * i for i in range(100) if i % 3 == 0)
for num in gen:
print(num)
# 寻找名字中带有两个e的人的名字
names = [[\'Tom\', \'Billy\', \'Jefferson\', \'Andrew\', \'Wesley\', \'Steven\',
\'Joe\'],
[\'Alice\', \'Jill\', \'Ana\', \'Wendy\', \'Jennifer\', \'Sherry\', \'Eva\']]
# 不⽤推导式和表达式
result = []
for first in names:
for name in first:
if name.count("e") >= 2:
result.append(name)
print(result)
# 推导式
gen = (name for first in names for name in first if name.count("e") >= 2)
for name in gen:
print(name)
生成器表达式和列表推导式的区别:
1. 列表推导式比较耗内存. 一次性加载. 生成器表达式几乎不占用内存. 使用的时候才分配和使用内存。
2. 得到的值不一样. 列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器。
举个栗子:
同样一篮子鸡蛋. 列表推导式: 直接拿到一篮子鸡蛋. 生成器表达式: 拿到一个老母鸡. 需要鸡蛋就给你下鸡蛋。
def func():
print(111)
yield 222
print(333)
yield 444
print(555)
g = func() #生成器g
g1 = (i for i in g) #生成器g1,但是g1的数据来源于g
g2 = (i for i in g1) #生成器g2,来源g1
print(list(g)) #获取g中的数据,这时func()才会被执行,结果为:111 333 555 [222,444]
print(list(g1))#获取g1中的数据,g1的数据来源于g,但是g已经取完了,g1也就没有数据,结果为[]
print(list(g2))#和g1同理,结果为[]
深坑----生成器,要值得时候才拿值。
字典推导式:
# 把字典中的key和value互换
dic = {\'a\': 1, \'b\': \'2\'}
new_dic = {dic[key]: key for key in dic}
print(new_dic)
# 在以下list中. 从lst1中获取的数据和lst2中相对应的位置的数据组成⼀个新字典
lst1 = [\'jay\', \'jj\', \'sylar\']
lst2 = [\'周杰伦\', \'林俊杰\', \'邱彦涛\']
dic = {lst1[i]: lst2[i] for i in range(len(lst1))}
print(dic)
集合推导式:
lst = [1, -1, 8, -8, 12]
# 绝对值去重
s = {abs(i) for i in lst}
print(s)
总结: 推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式
生成器表达式: (结果 for 变量 in 可迭代对象 if 条件筛选)
生成器表达式可以直接获取到生成器对象. 生成器对象可以直接进行for循环. 生成器具有惰性机制。
def add(a,b):
return a+b
def test():
for r_i in range(4):
yield r_i
g = test()
for n in [2,10]:
g = (add(n,i) for i in g)
print(list(g))
# 结果:[20, 21, 22, 23]
以上是关于2018.8.13 python中生成器和生成器表达式的主要内容,如果未能解决你的问题,请参考以下文章