生成器

一、什么是生成器?

生成器 是自定义的迭代器。

通过定义函数的方式,可以得到一个生成器对象。

在定义函数的时候,使用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))也可以的。

 

posted @ 2020-07-31 11:54  正在学Python  阅读(208)  评论(0编辑  收藏  举报