ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

生成器

2018-09-27 11:24:03  阅读:159  来源: 互联网

标签:


1.列表生成式
通过列表生成式,可以直接创建一个列表,但是受内存限制,列表容量有限,而且创建的列表太大,占用存储空间
a = [i*2 for i in range(10)]
print(a)
#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
2.生成器
定义:通过某种算法将列表推算出来,不用创建完整的list,节省大量内存空间,这种一边循环一边计算的机制,称作生成器,generator
特点:只有在调用的时候才产生数据,不会象列表一样先将所有数据加载到内存;只记录当前位置,不会象列表一样记录所有数据下标;只有一个方法__next__

2.1将列表生成式转化为生成器
b = (i*2 for i in range(10))            #将一个列表生成式转化生成器只需要将[]-->()
print(b)
#<generator object <genexpr> at 0x00492870>

for i in b:                                #通过循环调用生成器中数据
    print(i)
    if i > 5:             #如果在循环中终断程序,会接着调用生成器中的数据
        break
        
print(b.__next__())

print(b.__next__())                           #通过__next 方法一个个调用生成器中数据
print(b.__next__())
print(b.__next__())
print(b.__next__())


2.2通过函数实现生成器

斐波那契数列:除第一个和第二个数之外,任意一个数都可以由前两个数相加得到:
1,1,2,3,5,8,13,21,34...........
用函数实现斐波那契数列如下:
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        print(b)
        a,b = b,a+b             #注:a,b = b,a+b 相当于t = (b,a+b) a=t[0] b=t[1]
        n = n + 1
    return "done"
fib(10)
将上面函数变成生成器,只要把函数中的print(b)改成yeild 即可:
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        #print(b)
        yield b                 #当程序执行到yield会中断,直到下次调用接着执行
        a,b = b,a+b             #注:a,b = b,a+b 相当于t = (b,a+b) a=t[0] b=t[1]
        n = n + 1
    return "--done--"

print(fib(10))
<generator object fib at 0x00572870>

生成器调用:

f = fib(10)

for i in f:                       #使用for循环调用生成器数据
    print(i)

print(f.__next__())               #使用__next__调用
print(f.__next__())               #由于生成器会记录当前位置,这个时候停止生成器去干别的,下次会接着执行
print("----------------")
print(f.__next__())
print("-----------------")

使用__next__方法调用生成器数据超过指定的范围出现报错,报错信息:StopIteration: --done--
可以使用以下方法执行该生成器,将这个报错信息抓出正常返回:
while True:
    try:
        x = f.__next__()
        print("f:",x)
    except StopIteration as e:
        print("generator return value",e.value)
        break

3.生成器实现单线程下的并行效果,生产者消费者模型

import time
def consumer(name):
    print("%s 开始准备吃包子"%(name))
    while True:
        baozi = yield                           #每调用一次生成器,每次在执行到yield的时候会跳出,直到下次调用接着执行
        print("包子%s来了,被%s吃了"%(baozi,name))

def produer(name):
    c1 = consumer("A")                          #consumer是生成器,将其赋值给c1,c2 当用__next__方法调用时,c1和c2分别执行到yield跳出继续执行produer函数
    c2 = consumer("B")
    c1.__next__()                               #执行consumer这个生成器,当执行到yield时中断跳出
    c2.__next__()                               #执行consumer这个生成器,当执行到yield时中断跳出
    print("开始做包子了")
    for i in range(10):                            
       time.sleep(1)
       c1.send(i)                               #__next__只是在调用yield,而send在调用的同时还会给yield传值
       c2.send(i)

# produer("cx")

#注:如果是函数直接consumer("A")  就会执行,但有yield之后就变成生成器,必须使用循环,或者next方法调用才会执行


标签:
来源: http://blog.51cto.com/fengxiaoli/2286452

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有