day13

1. 生成器

# 生成器的本质就是迭代器
# 生成器的特点和迭代器一样,取值方式和迭代器一样(__next__(), send(): 给上一个yield传值
# 生成器其实就是手写的迭代器
    
生成器的三种生成办法:
    1.通过生成器函数*
    2.通过生成器表达式创建生成器*
    3.通过数据转换(这次没学)

2. 生成器函数

1. 什么是生成器函数
  # 函数中有yield,name这个函数就是生成器函数
  def
func():    print("我是周杰伦")    yield "昆凌" # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数    print("我是王力宏")    yield "李云迪???"    print("我是笛卡尔积")    yield "笛卡尔积是谁"   # print("你好啊") # 最后一个yield之后如果再进行__next__ 会报错   g = func() # 不会执行函数, 拿到的是生成器.   print(g.__next__()) # 周杰伦   print(g.__next__()) # 王力宏   print(g.__next__()) # 笛卡尔积   print(g.__next__()) # 执行下一个yield   # 函数中如果有yield 这个函数就是生成器函数. 生成器函数() 获取的是生成器. 这个时候不执行函数   # return 直接返回结果, 结束函数的调用   # yield 返回结果, 可以让函数分段执行   # g.__next__() # 执行函数. 执行到下一个yield   # g.__next__() # 继续执行函数到下一个yield
2. 生成器的好处之一: 不占用内存

  #
一次性拿出所有的放在列表里,占用内存   def order():    lst = []    for i in range(1000):    lst.append("衣服" + str(i))    return lst   ret = order()   print(ret)   # 生成器,一次拿出一个,不占用内存   def order():    for i in range(1000):    yield "衣服" + str(i)   g = order() # 获取生成器,不执行函数   mingwei = g.__next__()   print(mingwei) # 衣服0   zhaoyining = g.__next__()   print(zhaoyining) # 衣服1
3. send()方法
    # send() 和 __next__是一样的. 可以执行到下一个yield
    # send() 还可以给上一个yield位置传值, 不能给最后⼀个yield发送值. 在第⼀次执⾏⽣成器代码的时候不能使⽤send()
    
    例1:
        def func():
            print("我是第一段")
            a = yield 123
            print(a)
            print("闫子哲是第二段")
            b = yield 456
            print(b)
            print("理想是第三段")
            c = yield 789
            print(c)
            print("刘伟是最后一段")
            d = yield 666   # 最后收尾一定是yield

        g = func()  # 获取生成器,不执行函数

        print(g.__next__()) # 没有上一个yield 所以不能使用send() 开头必须是__next__()
        print(g.send("煎饼果子"))
        print(g.send("韭菜盒子"))
        print(g.send("锅包肉"))

    例2:
        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)
        ret3 = gen.send("狗粮")
        print(ret3)
        ret4 = gen.send("猫粮")
        print(ret4)
4. 拿生成器里所有的东西

  def func(): yield 1 yield 13 yield 26 yield 88 yield 46 # 现在func() 是生成器,然后for迭代生成器 for i in func(): # for的内部一定有__next__() print(i) 结果: 1 13 26 88 46 # 还可以这样拿所有值 print(list(func())) # 内部都有__next__() 结果: [1, 13, 26, 88, 46]

 4. 各种推导式

1. 列表推导式
    lst = []
    for i in range(1, 16):
        lst.append("python" + str(i))
    print(lst)
    
    列表推导式: 用一句话生成一个列表
    lst = ["python"+str(j) for j in range(1, 16)]
    print(lst)
    
    语法: [结果 for循环 判断]
    
    例1:
    # 100以内的奇数
    lst = [i for i in range(100) if i%2==1]
    print(lst)
    
    例2:
    # 100以内能被3整除的数的平方
    lst = [i*i for i in range(100) if i%3==0]
    print(lst)

    例3:
    # 寻找名字中带有两个e的⼈的名字
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

    # for循环完成
    lst = []
    for line in names:
        for name in line:
            if name.count("e") == 2:
                lst.append(name)
    print(lst)


    # 列表推导式完成
    lst = [name for line in names for name in line if name.count("e") == 2]
    print(lst)
2. 字典推导式
    # 把[11, 22, 33, 44] 变成 {0:11,1:22,2;33}
    lst = [11, 22, 33, 44]
    dic = {i:lst[i] for i in range(len(lst)) if i < 2}  # 字典推导式就一行
    print(dic)
    
    语法: {k:v for循环 条件筛选}

    例1:
    # 把key和value位置反过来
    dic = {"JJ": "林俊杰", "jay": "周杰伦", "zs": "赵四", "ln": "刘能"}
    dic = {v: k for k, v in dic.items()}
    print(dic)
3. set(集合)推导式
    首先再来回顾一下set(集合):
            1. set去重复
            2. set本身是不可哈希的(可变的)
            3. set中的元素是可哈希的(不可变的)

    # 集合推导式
    s = {i for i in range(100)}  # 可去重复
    print(s)

    语法: {i for循环 条件判断}

    例: 将数据去重
   lst
= [1, 1, 4, 6, 7, 4, 2, 2]    # 转换成集合再转换回去 s = set(lst)  print(s)  结果: {1, 2, 4, 6, 7}  # 直接用集合推导式  s = {el for el in lst}  print(s) 结果: {1, 2, 4, 6, 7}

5. 生成器表达式

    # 生成器表达式
    tu = (i for i in range(10))  # 没有元组推导式.  生成器表达式
    print(tu)  # 生成器
    print(tu.__next__())  # 0
    print(tu.__next__())  # 1
    print(tu.__next__())  # 2
    print(tu.__next__())  # 3
    print(tu.__next__())  # 4
    print(tu.__next__())  # 5
    print(tu.__next__())  # 6
    print(tu.__next__())  # 7
    print(tu.__next__())  # 8
    print(tu.__next__())  # 9
    print(tu.__next__())  # 第11个报错

    # 生成机制比较
    lst = [i for i in range(10)]  # 列表一下子拿出所有值
    print(lst)
    结果: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    gen = (i for i in range(10))  # 生成器, 惰性机制(要一个值,给一个值)
    print(gen.__next__())
    结果: 0
# 深坑==> ⽣成器. 要值得时候才拿值. (这个值拿过就没有了)

例1:
    # 生成器函数
    def func():
        print(111)
        yield 222
        yield 333

    g = func()  # 获取生成器
    g1 = (i for i in g)  # 生成器
    g2 = (i for i in g1)  # 生成器

    print(list(g))  # ??? [222]. g从源头func()把数据拿走了
    print(list(g1))  # ??? []  g1找g要数据,g找源头拿数据,源头已经没有数据了
    print(list(g2))  # ??? []  同理g1

例2:
# 分析这道面试题
    # 求和
    def add(a, b):
        return a + b

    # 生成器函数  # 0-3
    def test():
        for r_i in range(4):
            yield r_i

    # 0,1,2,3
    g = test()  # 获取生成器

    #
    for n in [2, 10]:
        g = (add(n, i) for i in g)

    # 到最后往里面放值就对了(不到最后不往里面放值)
    print(list(g))  # 获取生成器里面的所有值
    结果: [20, 21, 22, 23]    
   print(list(g)) # g里面的东西取完了 第二次再拿就是[] 结果: []

 

posted @ 2019-08-07 09:13  magickang  阅读(134)  评论(0编辑  收藏  举报