zoukankan      html  css  js  c++  java
  • 生成器的推导式 表达式

    一  生成器

    生成器的本质就是迭代器

    1 生成器的特点和迭代器一样 取值方式和迭代器一样(_next_(),send():给上一个yield传值

    2 生成器一般由生成器函数或者生成器表达式来创建

    3 其实就是手写的生成器

    4 在pytion中有三种方式来获取生成器

      通过生成器函数

     通过各种推导式来实现生成器

     通过数据的转换也可以获取生成器

    特点:

    1 惰性机制

    2只能向前

    3节省内存

    list中拿数据是全部一起拿,不是一个一个拿,里面有__next__  for 循环中也有__next__

    列如:

    def func():
        print("111")
        return 222     return返回一个值
    ret =func()
    print(ret)
    结果:
    111
    222

    将函数中的return换成yield就是生成器

    1 def func():
    2    print("111")
    3    yield 222  yield 就是一个生成器函数  
    4 ret =func()   形成一个生成器
    5 print(ret)
    结果:

    <generator object func at 0X10597ff68>

    通过执行_next_()来执行以下生成器

     1 def func():
     2 print("111")
     3 yield 222
     4 genner =func()   这个时候函数不会执行 而是获取生成器
     5 ret =genner.__next__()   这个时候函数才能执行 yield的作用和return一样 也是返回数据
     6 print(ret)
     7 
     8 
     9 结果:
    10 111
    11 222
    View Code

    yield是分段来执行一个函数 而return是直接停止执行函数

     1 def func():
     2 print("111")
     3 yield 222
     4 print("333")
     5 yiled 444
     6 gener =func()
     7 ret =genner._next_()
     8 print(ret)
     9 ret2=genner._next_()
    10 print(ret2)
    11 ret3=genner._next_()   最后一个yield执行完毕 再次_next_()程序会报错
    12 print(ret3)
    13 
    14 
    15 结果: 111 Traceback (most recent call last): 222 333  File "/Users/sylar/PycharmProjects/oldboy/iterator.py", line 55, in <module> 444    ret3 = gener.__next__()  # 最后⼀一个yield执⾏行行完毕. 再次__next__()程序报错, 也 就是说. 和return⽆无关了了. StopIteration
    16  
    View Code
     1 def func():
     2 print("111")
     3 yield 222
     4 print("333")
     5 yiled 444
     6 gener =func()
     7 ret =genner._next_()
     8 print(ret)
     9 ret2=genner._next_()
    10 print(ret2)
    11 ret3=genner._next_()   最后一个yield执行完毕 再次_next_()程序会报错
    12 print(ret3)
    13 
    14 
    15 结果: 111 Traceback (most recent call last): 222 333  File "/Users/sylar/PycharmProjects/oldboy/iterator.py", line 55, in <module> 444    ret3 = gener.__next__()  # 最后⼀一个yield执⾏行行完毕. 再次__next__()程序报错, 也 就是说. 和return⽆无关了了. StopIteration
    16  
    View Code

    当程序运行完最后一个yield 那么后面进行_next_()程序会报错

    来个实列

    采购10000套学士服 直接造出来10000 一次性给完

    def cloth():
    lst=[]
    for i in range(0,10000):
    lst.append("衣服"+str(i))
    return lst
    c1 =cloth()
    

     我想要一套一套拿衣服 该怎么办呢

    1 def cloth():
    2 for i in range(0,10000):
    3 yield"衣服"+str(i)
    4 cl =cloth()
    5 print(cl.__next__())
    6 print(cl.__next__())
    7 print(cl.__next__())
    8 print(cl.__next__())   一个一个取
    View Code

    区别: 第一种是直接一次性全部拿出来 会很占用内存 第二种使用生成器 一次就一个 用多少生成多少 生成器是一个一个的指向下一个 不会回去 __next__()到哪 指针就指到哪儿 下一次继续获取指针指向的值

    接下来看send()方法 send和__next__一样都可以让生成器执行下一个yield    send()的()里面必须给定参数

     1 def eat():
     2 print("我吃什么啊")
     3 a =yield 
     4 print("a"=,a)
     5 b=yield
     6 print("b"=,b)
     7 c=yield
     8 print("c"=,c)
     9 yield
    10 
    11 gen=eat()
    12 ret1=gen.__next__()
    13 print(ret1)
    14 ret2=grn.__next__()
    15 print(ret2)
    16 ret3=gen.__next__()
    17 print(ret3)
    18 ret4=gen.__next__()
    19 print(ret4)
    View Code

    send和__next__()区别:

    1 send和next()都是让生成器向下走一次

    2send可以给上一次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
    

     二 列表推导式,生成器表达式以及其他推导式

    lst =[]
    for i in range(1,15):
    lst.append(i)
    print(lst)
    

    替换成列表推导式

    lst=[i for i in range(1,15)]
    print(lst)
    

    例如: 从Pythion1期到pytion14期写入列表lst:

    lst=['pytion%s' % i for i in range(1,15)]
    print(lst)
    

     我们还可以对列表中的数据进行筛选

    筛选模式:

    [结果 for 变量 in 可迭代对象 if 条件]

    获取1-100内所有的偶数
    lst =[i for i in range(1,100) if i %2==0]
    print(lst)
    

    生成器表达式和列表推导式的语法基本上是一样的 只是把[]替换成()

    gen =(i for i in range(10))
    print(gen)
    结果:
    <generator object <genexpr> at 0x106768f10> 

     打印的结果就是一个生成器,我们可以使用for循环来循环这个生成器

    gen=("马化腾我第%s次爱你" % i for i in range(10))
    for i in gen:
    print(i)

    二生成器函数

    和普通函数没有区别 里面的yield的函数就是生成器函数

    生成器函数在执行的时候 默认不会执行函数体 返回生成器

    通过生成器的_next_()分段执行这个函数

    send()给上一个yield传值 不能在开头(没有上一个yield),最后一个yield也不能用send()

    三 推导式

    1 列表推导式[结果 for循环 条件筛选]

    2字典推导式[k,v for循环 条件筛选}

    把字典中的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)

    3集合推导式{k for循环 条件}

    集合的特点:无序,不重复  所以集合推导式自带去重的功能
    lst=[1,-1,8,-8,12]
    s ={abs(i) for i in lst}
    print(s)

    总结:推导式有列表推导式,字典推导式,集合推导式,没有元组推导式

    四 生成器表达式  (拿到的是一个生成器,只有执行__next__才能取值)

    (结果 for循环 条件)

    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 i in names:
      for name in i:
        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
    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 获取到222 g完毕
    print(list(g1))  获取g1中的数据 g1的数据来源是g 但是g 已经取完了 g1也没有数据
    print(list(g2)) 和g1 同理
    def add(a,b):
    retern 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))
    
    
    惰性机制,不到最后不会拿值
  • 相关阅读:
    LeetCode344. 反转字符串
    LeetCode59. 螺旋矩阵 II
    LeetCode209. 长度最小的子数组
    LeetCode383. 赎金信
    cannot be cast to javax.servlet.Servlet
    求组合
    数据库系统概论王珊第四版 答案
    数据库复习
    dfs-bfs
    dfs
  • 原文地址:https://www.cnblogs.com/mlhz/p/9469124.html
Copyright © 2011-2022 走看看