zoukankan      html  css  js  c++  java
  • 20180718 (生成器函数,表达式和列表字典集合推导式)

    一.生成器和生成器函数

    生成器的实质就是迭代器

    在Python中有三种方式来获取生成器:

      1.通过生成器函数           yield 就是生成器函数

      2.通过生成器表达式创建生成器

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

    例如:

      def func():

        print("我是周杰伦")

        yield "昆凌"

      ret = func()      =====>这里是通过func()函数来创建一个生成器     ====>如果光执行func()   打印出来的是空   没有东西,因为它本身是个生成器,但没有为它赋予值

      print(ret)          =======>打印出来的结果是生成器的内存地址

    例如:       .__next__()   是下一个的意思,向下执行

      def func():

        print("我是周杰伦")

        yield "昆凌"

      g = func()

      print(g.__next__())   ======>打印出来的结果是"我是周杰伦"  "昆凌"

    例如:

      def func():

        print("我是周杰伦")

        return "昆凌"

      print(func())               ======>打印出来的结果是"我是周杰伦"   "昆凌"

    return 与 yield 的区别

    1.return    直接返回结果,结束函数的调用

    2.yield      返回结果,可以让函数分段执行

    例如:

      def func():

        print("AA")

        yield "aa"

        print("BB")

        yield "bb"

        #print("CC")              =====>如果没有这两行或者是没有最后一行 ,最后一个.__next__()仍会继续执行,但是没有东西,所以就会报错

        #yield "cc"

      g = func()

      print(g.__next__())           ======> "AA" "aa"

      print(g.__next__())           ======>"BB" "bb"

      print(g.__next__())           ======>(如果存在print("CC")和yield "cc"这两行  执行出来CC和cc)

    生成器有一个有点就是节省内存

    例如:    运用生成器的好处就是可以节省内存,需要一件的时候就拿一件,但是最后的结果还是这100件

      def func():                                 

        i = 1

        while i < 101:

          yield "衣服%s" % i

          i = i + 1

      g = gen()

      print(g.__next__())                  ===>衣服1                  ,__next__() 到哪里,就拿到哪里

      print(g.__next__())                  ===>衣服2

    例如: 

      def func():

        lst = []

        for i in range(1,101):

          lst.append("衣服%s" % i)

        return lst                                    =========>这个执行出来的是将全部的衣服放进列表里全部打印出来   这样耗时又费空间内存

      func()

    例如:

      def func():

        yield 11

        yield 22

        yield 33

      g = func()                  =====>拿到的是生成器,生成器的本质是迭代器,迭代器可以被迭代,生成器的本身就是迭代器,所以生成器可以直接执行for循环

      for i in g:                                ======>for循环本质是执行的是  .__next__()

        print(i)                    =====>打印出来的结果是11 22 33遍历循环

    send 和 .__next__()的区别:

    1.send()  和  .__next__()   都可以让生成器向下执行一次

    2.send可以给上一个yield传一个值,但是不能给最后一个yield传值,并且在第一次执行生成器的时候不能使用send()

    例如: send例子

      def func():

        print("AA")

        a = yield "aa"

        print(a)

        print("BB")

        yield "bb"

        print(a)

        print("CC")

        yield "cc"

      g = func()

      print(g.__next__())             ====>"AA""aa"

      print(g.send(1))                  =====> 1 "BB" "bb"

      print(g.__next__())             =====> "CC" "cc"

    二.列表的推导式

    语法:[最终结果 for 变量 in 可迭代对象 if 筛选]   

    列表推导式比较耗内存,得到一个列表

    例如:  (常规写法)

      lst = []

      for i in range(1,15):

        lst.append("python%s" % i)

      print(lst)                  ======>打印出来是["python1","python2","python3"......"python14"]

    例如:    列表推导式写法

      lst = ["python%s" % i for i in range(1,15)]

      print(lst)

    例如:打印1~100能被3整除的数   放在列表里

      lst = [i for i in range(1,101) if i %3 == 0)]

    例如:打印100以内能被3整除的数的平方

      lst = [i**2 for i in range(1,101) if i %3 == 0]

    例如:找出名字中带有两个e的人的名字

       names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,'Joe'],['Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry' , 'Eva']]

      lst = [ii for i in names for ii in i if ii.count("e") == 2]

    三.生成器表达式    

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

    语法:(结果 for 变量 in 可迭代对象 if 筛选)   

    生成器表达式几乎不占内存,获取的是一个生成器

    例如:

      gen = (i for i in range(10))

      print(gen)             =====>打印出来的是生成器    只有内存地址

    例如:

      gen = ("麻花藤我第%s次爱你" % i for i in range(10))

      for i in gen:

        print(i)

    生成器表达式  和   列表推导式  的区别:

    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     g2的数据来源于g1

      print(list(g))          ======>111  [222]                 获取g中的数据,这时func()才会被执行,打印111,获取到222  g执行完毕

      print(list(g1))        ======>  []        #获取g1的数据  g1的数据来源是g  但是g已经取完了   g1也就没有了数据

      print(list(g2))        ======>  []        #同样g2也没有数据

    五.字典推导式

    语法:{结果 for 变量 in 可迭代对象 if 筛选}    ====>结果是k:v

    例如:

      dic = {"a":1,"b":2}

      new_dic = {dic[key]:key for key in dic}

      print(new_dic)

    例如:

      lst1 = ["AA","BB","CC"]

      lst2 = ["aa","bb","cc"]

      dic = {lst1[i] : lst2[i] for i in range(len(lst1))}

          =======>{"AA":"aa","BB":"bb","CC":"cc"}

    六.集合推导式   (自动去重)

    集合推导式可以帮我们直接生成一个集合,集合的特点是无序,不重复,所以集合推导式自带去重功能

    语法:{结果 for 变量 in 可迭代对象 if 筛选}    ====>结果是k

    例如:

      lst = ["AA","BB","CC","DD","AA","BB"]

      s = {i for i in lst}

      print(s)    ======>{"AA","BB","CC","DD"}

    变态面试题

      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]

      for n in [2,10]:                #n的值为2   10

        g = (add(n,i) for i in g)

    当程序循环第一次的时候   n = 2   但是循环没有结束,不执行

      g = (add(n,i) for i in test())

    当程序循环第二次的时候  n = 10   到print()的时候才执行

      g = (add(n,i) for i in (add(n,i) for i in test()))

    当时这个时候不执行,只有当程序执行到print的时候,才会将n的值带入 此时n = 10

     

  • 相关阅读:
    2019年11月体重管理进展
    云锵投资 2019 年 11 月简报
    2019年10月体重管理进展
    云锵投资 2019 年 10 月简报
    2019年9月体重管理进展
    云锵投资 2019 年 09 月简报
    2019年8月体重管理进展
    云锵投资 2019 年 08 月简报
    分布式系统发展史
    2019年7月体重管理进展
  • 原文地址:https://www.cnblogs.com/lhy979/p/9330026.html
Copyright © 2011-2022 走看看