Day4-生成器generator

列表生成式

需求:列表[0,1,2,3,4,5,6,7,8,9]每个值加1,如何实现?

方法1:列表追加

 1 >>> a = [0,1,2,3,4,5,6,7,8,9]
 2 >>> b = []
 3 >>> for i in range(10):
 4 ...     b.append(i+1)
 5 ...
 6 >>> b
 7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 8 >>> a = b
 9 >>> a
10 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

方法2:原值修改enumerate

1 >>> a = [0,1,2,3,4,5,6,7,8,9]
2 >>> for index,i in enumerate(a):
3 ...     a[index] += 1
4 ...
5 >>> a
6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

方法3:map函数

 1 >>> a = [0,1,2,3,4,5,6,7,8,9]
 2 >>> a = map(lambda x:x+1,a)
 3 >>> a
 4 <map object at 0x000000000299FF60>
 5 >>> for i in a: print(i)
 6 ...
 7 1
 8 2
 9 3
10 4
11 5
12 6
13 7
14 8
15 9
16 10

方法4:列表生成,作用:使代码更简洁

1 >>> a = [i+1 for i in range(10)]
2 >>> a
3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

生成器

当list列表很大,比如100万条,只使用几个,而不是使用那么多,如果全部放进内容占用空间很大,使用一种机制:边循环边计算,称为生成器

元组:

 1 >>> b = (i*2 for i in range(10))
 2 >>> b
 3 <generator object <genexpr> at 0x00000000029981A8>
 4 >>> for i in b:
 5 ...     print(i)
 6 ...
 7 0
 8 2
 9 4
10 6
11 8
12 10
13 12
14 14
15 16
16 18

列表:

1 >>> c = [i*2 for i in range(10)]
2 >>> c
3 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

两者区别:最外层的[]和(),一个是list,一个是generator生成器。

如何打印其中的元素:

列表list:

1 >>> c[9]
2 18
3 >>> len(c)
4 10

元组generator:生成器使用元组,只有被调用了才会生成数据,调用哪生成哪。调用方法:next()

1 >>> b[9] #生成器没有像列表一样的下标操作
2 Traceback (most recent call last):
3   File "<stdin>", line 1, in <module>
4 TypeError: ‘generator‘ object is not subscriptable

 1 >>> b = (i*2 for i in range(10))
 2 >>> next(b)
 3 0
 4 >>> next(b)
 5 2
 6 >>> next(b)
 7 4
 8 >>> next(b)
 9 6
10 >>> next(b)
11 8
12 >>> next(b)
13 10
14 >>> next(b)
15 12
16 >>> next(b)
17 14
18 >>> next(b)
19 16
20 >>> next(b)
21 18
22 >>> next(b) #next只记录当前位置,调用到最后一个再调用就会报错
23 Traceback (most recent call last):
24   File "<stdin>", line 1, in <module>
25 StopIteration

next()方法调用到最后一个后再调用就会抛出StopIteration错误异常,正确的方法:

 1 >>> g = ( i*2 for i in range(10))
 2 >>> for n in g:
 3 ...     print(n)
 4 ...
 5 0
 6 2
 7 4
 8 6
 9 8
10 10
11 12
12 14
13 16
14 18

举例1:斐波那契数列1,1,2,3,5,8,13...,函数代码为

 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         print(b)
 5         a, b = b, a + b
 6         n = n + 1
 7     return ‘done‘
 8
 9 fib(10)
10 1
11 1
12 2
13 3
14 ...
15 55

赋值语句:a,b = b,a+b  相当于 t=(b,a+b) a=t[0] b=t[1]

生成器写法:

 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         #print(b)
 5         yield(b) #有yield关键字就不是普通函数,而是一个生成器generator
 6         a, b = b, a + b
 7         n = n + 1
 8     return ‘异常了‘ #11个next方法执行后,就会抛出异常Stop Iteration:异常了,所以return返回的是异常消息
 9
10 f=fib(10) #生成器必须被调用才能生效
11 #print(f.__next__()) #使用next方法调用
12 for i in f:  #正确调用方式如下
13     print(i)

总结:有yield函数就是一个生成器,return返回异常消息。yield保存函数中断状态,想什么时候回来就什么时候回来。

生成器的作用:函数是顺序执行,遇到return或最后一行语句就结束执行;生成器在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。(断点执行下看看)

yield实现单线程情况下并发!!!

 举例2:典型的生产者消费者模型

 1 import time
 2 def consumer(name):
 3     print("%s准备吃包子了"%name)
 4     while True:
 5         baozi = yield #没有yield返回值,表示为空
 6         print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 7 c = consumer("A")
 8 c.__next__()
 9 执行结果:
10 A准备吃包子了
11
12 再添加一行代码:
13 c.__next__()
14 包子[None]来了,被[A]吃了
15
16 分析:
17 第一次程序执行顺序:
18 def consumer---c=consumer("A")使得c变成generator生成器---c.__next__()调用生成器--def consumer(name = "A")--print---while True---baozi=yield--返回为空退出,底下的print(包子被谁吃了)不执行
19
20 第二次程序执行顺序:
21 def consumer---c=consumer("A")使得c变成generator生成器---c.__next__()调用生成器--def consumer(name = "A")--print---while True---baozi=yield--第二个c.__next__()---baozi=yield---print(包子被谁吃了)---baozi=yield---返回为空退出

注:生成器只有g.__next()__方法调用,同t = next(g)一样。

执行结果:

A准备吃包子了
包子[None]来了,被[A]吃了

 1 import time
 2 def consumer(name):
 3     print("%s准备吃包子了"%name)
 4     while True:
 5         baozi = yield #没有yield返回值,表示为空
 6         print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 7 c = consumer("A")
 8 c.__next__()
 9
10 b1 = "韭菜馅"
11 c.send(b1)
12 c.__next__()
13
14
15 执行结果:
16 A准备吃包子了
17 包子[韭菜馅]来了,被[A]吃了
18 包子[None]来了,被[A]吃了
19
20 next和send区别?
21 next只是调用yield,send不仅调用还给yield传值

最终代码:单线程下的并行效果叫协程。

 1 import time
 2 def consumer(name):
 3     print("%s准备吃包子了"%name)
 4     while True:
 5         baozi = yield #没有yield返回值,表示为空
 6         print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 7 # c = consumer("A")
 8 # c.__next__()
 9 #
10 # b1 = "韭菜馅"
11 # c.send(b1)
12
13 def producer(name):
14     c = consumer(‘A‘) #两个消费者
15     c2 = consumer(‘B‘)
16     c.__next__() #调用,打印“准备吃包子”
17     c2.__next__()
18     print("开始准备做包子了")
19     for i in range(10):
20         time.sleep(1) #每1s钟做2个包子
21         print("做了2个包子")
22         c.send(i)
23         c2.send(i)
24
25 producer("alex")
26
27 执行结果:
28 A准备吃包子了
29 B准备吃包子了
30 开始准备做包子了
31
32 做了2个包子
33 包子[0]来了,被[A]吃了
34 包子[0]来了,被[B]吃了
35 ....
36 做了2个包子
37 包子[9]来了,被[A]吃了
38 包子[9]来了,被[B]吃了
39
40 分析:三行三行的打印,好像是并行的,类似nginx异步IO的效果

时间: 2024-08-02 04:46:43

Day4-生成器generator的相关文章

Python高级编程之生成器(Generator)与coroutine(一):Generator

这是一系列的文章,会从基础开始一步步的介绍Python中的Generator以及coroutine(协程)(主要是介绍coroutine),并且详细的讲述了Python中coroutine的各种高级用法,最后会用coroutine实现一个简单的多任务的操作系统. 其实也是看完这篇文章的学习笔记吧!O(∩_∩)O 生成器(Generator) 什么是生成器?在Python中,生成器(Generator)是一个带有yield关键字的函数 1 def gene(): 2 a = 1 3 print "

ES6中的迭代器(Iterator)和生成器(Generator)

前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 本文将详细介

生成器generator

生成器generator 定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 代码: def cash_out(amount): while amount >0: amount -= 1 yield 1<br> print("擦,又来取钱了...败家子!") ATM = cash_out(5) print("取到钱 %s 万" % ATM.__next__())

生成器(generator)内部解析

#http://kb.cnblogs.com/page/87128/(未看完) 2.7. 生成器(generator) 生成器是调用一个生成器函数(generator function)返回的对象,多用于集合对象的迭代. __iter__: 仅仅是一个可迭代的标记. gi_code: 生成器对应的code对象. gi_frame: 生成器对应的frame对象. gi_running: 生成器函数是否在执行.生成器函数在yield以后.执行yield的下一行代码前处于frozen状态,此时这个属性

Python 生成器generator

列表的问题列表生成器可以直接创建一个表,但是,如果一个表中有100万个元素,那么这个表太占空间,而且往往我们仅仅需要访问前面几个元素,后面绝大多数元素占用的空间都白白浪费了. 生成器如果列表元素可以按照某种算法推算出来,那我们可以在循环的过程中不断的推算出后续的元素.而不用一开始就创建整个list.这样,节省了大量的空间.这种一遍循环一遍计算的机制,称为生成器:generator. 创建生成器generator.第一种方法:只要报一个列表生成式的[]改成(),就穿件了一个generator.创建

Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍

原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Generator Function的示例,这一小节,我们会介绍Python的coroutine,以及会有一个小例子,再接下来的文章中会以代码的形式一步步介绍coroutine的高级用法. coroutine(协程) 什么是coroutine?coroutine跟Generator有什么区别?下面先看一段

【25】Python生成器generator

列表生成式一个小题目:将里列表[0,1,2,3]里面的数值都加1.方法1: a=[0,1,2,3] b=[] for i in range(len(a)): b.append(i+1) a=b print(a) 方法2: a = [1,3,4,6,7,7,8] for index,i in enumerate(a): a[index] +=1 print(a) 方法3: a=[0,1,2,3,4] a=map(lambda x:x+1,a) print(a) for i in a: print(

Python之生成器(generator)和迭代器(Iterator)

generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,可以使用next()函数和send()函数恢复生成器. 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用.但是,不同于一般函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这个消耗的内存数量将大大减小.因此,生成器看起来像是一个函数,但是表现得像迭代

python生成器 Generator

生成器 Generator 什么是生成器? 生成器是能够动态提供数据的可迭代对象 生成器在程序运行时生成数据,与容器类不同,它通常不会在内存中保存大量的数据,而是现用现生成 生成器有两种: 生成器函数 生成器表达式 生成器函数 含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象 注: yield翻译为(产生或生成) yield 语句 语法: yield 表达式 说明: yield 用于 def函数中,目的是将此函数作用生成器函数使用yield 用来生成数据,供迭代器的next

生成器generator和迭代器Iterator

一.列表生成式       在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2,3,4,5]可以使用list(range(6)),但是如果想要生成[,,,,,]即[0,1,4,9,16,25]怎么做? #方法一:循环>>> L = []>>> for x in range(6):... L.append(x**2)...>>> L[