zoukankan      html  css  js  c++  java
  • python摸爬滚打之day12----生成器, 各种生成式

    1、生成器

     生成器的本质就是迭代器.

     1.1  获取生成

      1:  生成器函数

       函数中出现 "yield" 的函数就是一个生成器函数, 再次执行函数时就不是运行函数而是获取生成器. 

      2: 生成器推导式

       ( i for i in range( 20) )  ----> 不是元组生成式, 而是生成器推导式, 它获取的是一个生成器.

            gen = ( i for i in range( 20) ), gen就是一个生成器

     1.2  生成器取值方式:  

        1,  通过__next__()取值.     2 , 通过send(" ")取值并传值.

     1 def func():
     2     print("黄焖鸡")                # 1
     3     yield "黄焖鸡yield"            # 2
     4     print("烧鸭")            # 3
     5     yield "烧鸭yield"            # 4
     6     print("蒸鹿茸")            # 5
     7     yield "蒸鹿茸yield"            # 6
     8     print("蒸熊掌")
     9 
    10 gen = func()     # 函数中出现"yield" 时,表示该函数为生成器,获取生成器.
    11 print(gen)     #  结果是一个生成器地址. <generator object func at 0x000002798C873C78>
    12 gen.__next__()        # 取到函数体中yield的那行就停止(第1,2行),并将yield后面的内容返回给调用者
    13 print(gen.__next__())       # 再次调用就从上次停止的yield下行(第3行)开始运行,截止到第四行.
    14 print(gen.__next__())
    15 print(gen.__next__())     # 如果yield内容结束,还继续调用,则报错,但是print("蒸熊掌")还是会继续执行的
    生成器__next__()取值

     1.2  生成器本质就是迭代器, 如何满足迭代器的三个特点呢?

     1 def buy():
     2     lst = []
     3     for i in range(1000):
     4         lst.append("帽子%s" %(i))             # 把多有的帽子放在内存的列表里,占得内存大
     5     return lst
     6 print(buy())
     7 
     8 
     9 def buy_gen():
    10     for i in range(1000):
    11         yield "帽子%s" %(i)           # 不是一次性全部把帽子0.......帽子999放在内存,
    12                                       # 而是通过__next__()一个一个取,比较省内存,但是不能往前执行,
    13                                       # 满足迭代器的三个特点
    14 gen = buy_gen()
    15 print(gen.__next__())
    16 print(gen.__next__())
    17 print(gen.__next__())
    18 print(gen.__next__())
    如何满足迭代器的三个特点
     1 def baocaiming():
     2     print("蒸鹿茸")
     3     a = yield "蒸鹿茸yield"
     4     print("a=",a)
     5     print("蒸熊掌")
     6     b = yield "蒸熊掌yield"
     7     print("b=", b)
     8     print("烧花鸭")
     9     c = yield "烧花鸭yield"
    10     print("c=", c)
    11     print("烧子鹅")
    12 
    13 gen = baocaiming()   
    14 print(gen.__next__())       # 第一次只能用__next__()取值
    15 print(gen.send("a++"))      # 从上一次停止的yield开始执行,并将"a++"传给上次yield之前的变量a, a == "a++"    
    16 print(gen.send("b++"))
    17 print(gen.send("c++"))      # 函数里没有yield了,还继续调用,则报错,但是print("蒸熊掌")还是会继续执行的
    生成器send()取值

      send()取值方式机理?

    2、各种推导式

     2.1  列表推导式

      [ 结果  for循环  if条件 ]

     1 # 1到20 所有奇数的平方
     2 lst = [i**2 for i in range(20) if i % 2 == 1]
     3 print(lst)
     4 
     5 # 将 a = [3,6,9]   转化成---->   [(1,2,3),[4,5,6],[7,8,9]]
     6 print([(ele-2,ele-1,ele-0) for ele in a])
     7 
     8 # 查找名字里面有两个"e"的名字
     9 names = [
    10     ['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
    11     ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva'],
    12 ]
    13 print([r for i in names for r in i if r.count("e") == 2])
    列表推导式

     2.2  字典、集合推导式

      {结果  for循环  if条件}

    1 dic = {"张无忌":"赵敏", "杨过":"小龙女", "郭靖":"黄蓉"}   # 将键,值换成值,键
    2 new_dic = {v:k for k,v in dic.items()}
    3 print(new_dic)
    4 
    5 # lst = [11, 22, 33]  #  => {0:11, 1:22, 2:33}
    6 lst = [11, 22, 33]
    7 dic = {i:lst[i] for i in range(len(lst))}
    8 print(dic)
    字典推导式

     2.3  生成器推导式

       (结果  for循环  if条件)    注意: 不是元组推导式, 元组是没有推导式!

      生成器表达式和列表推导式有什么不同?

        1: 列表推导式是一次性加载完, 耗内存; 生成器表达式几乎不占内存, 只有取值时候才分配和使用内存;

        2: 列表推导式得到的是一个列表, 生成器表达式得到的是一个生成器.

     2.4  生成器的惰性机制?

     1 def func():
     2     print(111)
     3     yield(222)
     4 g = func()                  #  生成器 g
     5 g1 = (i for i in g)         #  生成器 g1, g1数据来源于g
     6 g2 = (i for i in g1)        #  生成器 g2, g2数据来源于g1
     7 # --------------------------------截至到此,还没有生成器拿过值
     8                             # 惰性机制----只要不访问就永远拿不到值
     9 print(list(g))     # ----> [222]  获取到g中的数据,此时才执行func()函数,将222返回给g.
    10 print(list(g1))    # ----> []   list(g)已经将生成器g中的数据拿完了,所以g1拿不到数据,只能为[]
    11 print(list(g2))    # ----> []   g2和g1一样,拿不到值.
    12 
    13 # list() 的机理?  (list()包含了for循环的机理)
    14 #  list() ----> 包含了for循环 ----> 通过__iter__()将可迭代对象转化成了
    15 #         迭代器 ----> 通过__next__()从迭代器里取值 ----> 将拿到的值添加进列表里
    生成器惰性机制

     2.5  yield from

       把可迭代对象中的每一个元素作为生成器的结果返回. 

    1 def gen():
    2     lst = ["⿇花藤", "胡辣汤", "微星牌饼铛", "Mac牌锅铲"]
    3     lst2 = ["饼铛还是微星的好", "联想不能煮鸡蛋", "微星就可以", "还可以烙饼"]
    4     yield from lst          # 把 lst中的每一个元素作为生成器的结果返回给调用者.
    5     yield from lst2       # 两个yield不会产生交替的效果.
    6 
    7 g = gen()
    8 for el in g:
    9     print(el)
    yield from
  • 相关阅读:
    Android笔记(三) 使得Activity之间可以跳转---Intent
    Python jQuery
    Python JavaScript BOM和DOM以及window对象
    Python JavaScript
    Python 前端CSS样式
    Python 前端CSS
    Python 前端 HTTP HTML标签
    Python mysql中的:视图 触发器 事务 存储过程 mysql内置函数 流程控制 b+树 索引 慢日志查询 权限管理
    Python pymysql模块
    Django进阶Model篇005
  • 原文地址:https://www.cnblogs.com/bk9527/p/9888818.html
Copyright © 2011-2022 走看看