码迷,mamicode.com
首页 > 编程语言 > 详细

2018.8.13 python中生成器和生成器表达式

时间:2018-08-13 20:52:47      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:替换   技术分享   game   传递值   生成器   执行   def   迭代   font   

主要内容:

         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中生成器和生成器表达式

标签:替换   技术分享   game   传递值   生成器   执行   def   迭代   font   

原文地址:https://www.cnblogs.com/fengchong/p/9470337.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!