生成器
一、什么是生成器?
生成器 是自定义的迭代器。
通过定义函数的方式,可以得到一个生成器对象。
在定义函数的时候,使用yield关键字。之后再调用函数,就可以得到一个生成器对象。
所以如何去自定义一个迭代器呢? 就是通过使用yield关键字定义函数后调用函数,就可以获得一个自定义的迭代器对象,也就是生成器对象。
迭代器如何去取值,生成器就如何取值 。调用函数的时候,会拿到生成器对象,如果要执行函数取值,还需要通过next方法。next方法 会调用执行函数,碰到yield 就停下来,再次调用next, 函数才会再次运行,函数所有值取进之后,再执行next方法,会抛出异常。
除了使用next 方法来执行函数,其实还可以使用send()方法。
def dog():
print("dog准备吃东西...“ )
while True:
x = yield # x拿到的是send给yield的值
print("dog吃了%s" %x)
g = dog() # 调用函数得到一个生成器对象g
g.send(None) # 第一次send传值给yiled的时候,必须是一个None值。相当于使用next(g)。必须要让函数挂起到某个位置,才能再给yield传值
g.send('骨头') # dog 吃了骨头
g.send('肉包子') # dog吃了肉包子
=======================================================》
yield 除了 可以接收send()传入的值,还可以用于函数返回值。用法类似于return。不过函数碰到return就停止,碰到yield是挂起,再次next 或者send的时候从挂起的地方继续运行。
def dog():
food_list = []
print("dog准备吃东西...“ )
while True:
x = yield food_list # x拿到的是send给yield的值
print("dog吃了%s" %x)
food_list.append(x)
g = dog() # 调用函数得到一个生成器对象g
res = g.send(None) # 第一次send传值给yiled的时候,必须是一个None值。相当于使用next(g)。必须要让函数挂起到某个位置,才能再给yield传值
print(res) # food_list = []
res = g.send('骨头') # dog 吃了骨头
print(res) # food_list = ['骨头‘]
res = g.send('肉包子') # dog吃了肉包子
print(res) # food_list = ['骨头‘,'肉包子']
二、生成式
1.列表生成式
l = ['a_l','b_l','c_l','d_l','e_l','a',]
l1 = [x for x in l if x.endswith('l')] # for循环拿出一个值,只要值满足条件(条件也可以省略,就是默认成 if True),就把X放到列表中。
相当于下面这段代码的操作,但是更精简。
l2 = []
for i in l:
if i.endswith('l'):
l2.append(i)
l3 = [x.upper() for x in l] # ['A_L', 'B_L', 'C_L', 'D_L', 'E_L', 'A']
l4 = [x.replace('_l','') for x in l] # ['a', 'b', 'c', 'd', 'e', 'a']
2.字典生成式
keys = ['name','age','gender']
dic = {key:[] for key in keys} # {'name': [], 'age': [], 'gender': []}
items = [('name','bob'),('age',16),('gender','male')]
dic2 = { x[0]:x[1] for x in items if x[0] != 'gender'} # {'name': 'bob', 'age': 16}
dic3 = {k:v for k,v in items if k != 'gender'} # {'name': 'bob', 'age': 16}
3.集合生成式
keys = ['name','age','gender']
set1 = {key for key in keys} # {'age', 'gender', 'name'}
4.元祖生成式(然鹅,没有元祖生成式)
g = (i for i in range(10) if i > 3) # <generator object <genexpr> at 0x002610B0>
带上小括号的可不是元祖生成式,他是生成器表达式。所以我们现在又得到了一个拿到生成器的方法啦。
print(sum(g)) # 不占用内存,括号还可以省略,print(sum(i for i in range(10) if i > 3))也可以的。