1. 内容大纲

    1. 生成器

      SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
      • yield
      • yield与 return
      • send方法(了解)
      • yield 与 yield from
    2. 生成器表达式,列表推导式

    3. 内置函数 I

  2. 具体内容:

    • 生成器

      • 生成器:python社区,生成器与迭代器看成是一种。生成器的本质就是迭代器。唯一的区别:生成器是需要我们自己用python代码构建的数据结构。迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来的(比如文件句柄,iter([1,2,3])。
        • 创建(获取)生成器的三种方式:
          • 通过生成器函数。
          • 通过生成器表达式。
          • python内置函数或者模块提供
      • 生成器函数获得生成器:
      函数:
      def func():
          print(111)
          print(222)
          return 3
      ret = func()
      print(ret)
      111
      222
      3
      
      生成器函数也叫生成器,通过生成器函数构建生成器:
      
      def func():
          print(11)
          yield 22
          yield 33
      ret = func()  #获取生成器对象
      print(ret) # <generator object func at 0x000002003A91B1A8>  #generator 生成器
      next(ret) # 11   next让指针停留在第一个yield后面。生成器取值但未打印
      print(next(ret)) # 33   生成器取值
      生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值:next会获取对应yield生成的元素。一个yield对应一个next,next超过yield数量(最后⼀个yield执⾏完毕. 再次next),就会报错
      
      def func():
          print(111)
          print(222)
          yield 3
          a = 1
          b = 2
          c = a + b
          print(c)
          yield 4
      ret = func()
      print(ret)#<generator object func at 0x000001D73472B1A8>
      print(next(ret))#next让指针停留在第一个yield后面。一个next对应一个yield
      # 111
      # 222
      # 3
      print(next(ret))#保留了上次的位置,从第一个yield后面开始执行,最终next让指针停留在第二个yield后面。一个next对应一个yield
      # 3
      # 4
      
      
      • yield 与 return的区别:

        return:一般在函数中只设置一个,它的作用是终止函数,并且给函数的执行者返回值。
        
        yield:只要函数中有yield,那么这个函数就是一个生成器函数(生成器),而不是函数了。在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器对象。
        yield:在生成器函数中可设置(存在)多个yield.,yield不会结束生成器函数,一个yield对应一个next。
      • 吃包子练习题:

        #非常直观,但占用内存
        def func():
            l1 =[]
            for i in range(1,5001):
                l1.append(f'{i}号包子')
            return l1
        ret = func()
        print(ret)
        
        #非常的节省内存,而且还可以保留上次的位置
        def gen_func():
            for i in range(1,5001):
                yield f'{i}号包子'
        ret = gen_func()
        print(ret)#<generator object gen_func at 0x0000016AD3D1B1A8>
        for i in range(200):  #从1号包子到200号包子
            print(next(ret))
        
        for i in range(300):  #从201号包子到500号包子,多次next包子的号码是按照顺序记录的。
            print(next(ret))
        
      • send方法(了解)

        # next只能获取yield生成的值,但是不能传递值
         def gen(name):
             print(f'{name} ready to eat')
             while 1:
                 food = yield
                 print(f'{name} start to eat {food}')
         dog = gen('alex')
         next(dog)  #alex ready to eat    第一次next让指针停留在第一个yield后面
         next(dog)  #alex start to eat None  能记住上次的位置,再次执行从yield后面开始执行,最后又停在yield后面
         next(dog)  #alex start to eat None  同上
        
        
        #send不仅能获取yield生成的值,还能传递值
         def gen(name):
             print(f'{name} ready to eat')
             while 1:
                 food = yield 222
                 print(f'{name} start to eat {food}')
         dog = gen('alex')##获取生成器对象
         next(dog)  # alex ready to eat  第一次必须用next让指针停留在第一个yield后面
         ret = dog.send('骨头')#alex start to eat 骨头
         print(ret)#222   # 与next一样,可以获取到yield的值
        
        
         def gen(name):
             print(f'{name} ready to eat')
             while 1:
                 food = yield
                 print(f'{name} start to eat {food}')
         dog = gen('alex')
         next(dog)#alex ready to eat
         # 可以给上一个yield发送值
         dog.send('骨头')#alex start to eat 骨头
         dog.send('狗粮')#alex start to eat 狗粮
         dog.send('香肠')#alex start to eat 香肠
        
        
        send 和 next()区别:
            相同点:
                send 和 next()都可以让生成器对应的yield向下执行一次。
                都可以获取到yield生成的值。
            不同点:
                第一次获取yield值只能用next不能用send(可以用send(None))。
                send可以给上一个yield置传递值。'''
        
      • yield 与 yield from

        yield from:可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回
        
        def func():
            l1 = [1,2,3,4,5]
            yield l1
        ret = func()
        print(ret)#<generator object func at 0x00000162756FB1A8>
        print(next(ret))#[1, 2, 3, 4, 5]
        
        def func():
            lst = ['卫龙','老冰棍','北冰洋','牛羊配']
            yield lst
        ret = func()
        print(ret)#<generator object func at 0x000001B7A853B0F8>
        print(next(ret))  # 只是返回一个列表['卫龙', '老冰棍', '北冰洋', '牛羊配']
        
        
        【面试题】
        def func():
            lst = ['卫龙','老冰棍','北冰洋','牛羊配']
            yield from lst  #将lst这个列表变成了迭代器返回,它会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
        '''  yield from lst 相当于下面的:
            yield '卫龙'
            yield '老冰棍'
            yield '北冰洋'
            yield '牛羊配'
        '''
        ret = func()
        print(ret)# <generator object func at 0x0000026314EFB0F8>
        print(next(ret))  #卫龙
        print(next(ret))  #老冰棍
        print(next(ret))  #北冰洋
        print(next(ret))  #牛羊配
        
        
        def func():
            l1 = [1, 2, 3, 4, 5]
            yield from l1
        ret = func()
        for i in range(5):
            print(next(ret))
        
        
        
        #有个小坑,
        yield from 是将列表中的每一个元素返回, 所以如果写两个yield from 并不会产生交替的效果
        
        def func():
            lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
            lst2 = ['馒头', '花卷', '豆包', '大饼']
            yield from lst1
            yield from lst2
        g = func()
        for i in g:
            print(i)
        # 卫龙
        # 老冰棍
        # 北冰洋
        # 牛羊配
        # 馒头
        # 花卷
        # 豆包
        # 大饼
        
        
    • 生成器表达式,列表推导式

      • 用一行代码构建一个比较复杂有规律的列表。

         l1 = []
         for i in range(1,11):
             l1.append(i)
         print(l1)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        
        #列表推导式:
         l1 = [i for i in range(1,11)]
         print(l1)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      • 字典推导式(了解)
        lst1 = ['jay', 'jj', 'meet']
        lst2 = ['周杰伦','林俊杰','元宝']
        dic = { lst2[i]: lst1[i] for i in range(len(lst1))}
        print(dic)#{'周杰伦': 'jay', '林俊杰': 'jj', '元宝': 'meet'}
        
        
        集合推导式(了解)
        print({i for i in range(1,11)})
      • 列表推导式:

        • 缺点:
             1,有毒。列表推导式只能构建比较复杂并且有规律的列表。 不要太着迷。
             2,超过三层循环才能构建成功的,就不建议用列表推导式。
             3,查找错误(debug模式)不行
          优点:
               一行构建,简单。
          
        • 循环模式:[变量(加工后的变量) for 变量 in iterable]

          # 将10以内所有整数的平方写入列表。
           ret = [i**2 for i in range(1,11)]
           print(ret)
          
          # 100以内所有的偶数写入列表.
           print([i for i in range(2, 101, 2)])
          
          # 从python1期到python100期写入列表lst
           print([f'python{i}期' for i in range(1,101)])
          
          #【*】一行代码构建[2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
           l1 = [i for i in range(2,11)] + list('JQKA')
           print(l1)#[2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
          
        • 筛选模式:[变量(加工后的变量) for 变量 in iterable if 条件]

          # 30以内能被3整除的数
           l1 = [i for i in range(1,31) if i%3 == 0]
           print(l1)
          
          # 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
           l1 = ['barry', 'ab', 'alex', 'wusir', 'xo']
           print([i.upper() for i in l1 if len(i) >= 3 ])
          
          # 含有两个'e'的所有的人名全部大写留下来
           names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
            1.正常做法:
             l1 = []
             for i in names:
                 for j in i:
                    if j.count('e') == 2:
                         l1.append(j)
             print(l1)#['Jefferson', 'Wesley', 'Steven', 'Jennifer']
            2.列表推导式
             print([j for i in names for j in i if j.count('e') == 2 ])# ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
          
          
      • 生成器表达式:
                    列表推导式与生成器表达式区别。
                     1.写法上: [] ()
                     2.iterable:可迭代对象   iterator:迭代器
        
        生成器表达式和列表推导式的区别:
        
        1.列表推导式比较耗内存,所有数据一次性加载到内存。而生成器表达式遵循迭代器协议,逐个产生元素。
        2.得到的值不一样,列表推导式得到的是一个列表。生成器表达式获取的是一个生成器。
        3.列表推导式一目了然,生成器表达式只是一个内存地址。
        
        • 与列表推导式的写法几乎一模一样,也有筛选模式,循环模式,多层循环构建。写法上只有一个不同:[] 换成 ().
          
           print([i for i in range(1,11)]) #列表推导式
           print((i for i in range(1,11))) #生成器表达式
          
           obj = (i for i in range(1,11))
           print(next(obj))
           print(next(obj))
           print(next(obj))
           print(next(obj))
           print(next(obj))
           #或者:
           for i in obj:
               print(i)
          
          
    • 内置函数 I

      #eval:执行字符串类型的代码,并返回最终结果。
          eval('2 + 2')  # 4
          n = 81
          eval("n + 4")  # 85
          eval('print(666)')  # 666
      
          eval 剥去字符串的外衣运算里面的代码,有返回值。网络传输的str input 输入的时候,sql注入等等绝对不能使用eval。
          s1 = '1 + 3'
          print(s1)# 1 + 3
          print(eval(s1))  #4  **
          s = '{"name": "alex"}'
          print(s,type(s))#{"name": "alex"} <class 'str'>
          print(dict(s)) # 不行
          print(eval(s),type(eval(s)))#{'name': 'alex'} <class 'dict'>
      
      
      #exec: 执行字符串类型的代码。 exec 与eval几乎一样, 处理代码流
          s = '''
          for i in [1,2,3]:
              print(i)
          '''
          exec(s)
      
          msg = """
          for i in range(10):
              print(i)
          """
          print(msg)  #for i in range(10):
                        #print(i)
          exec(msg)  0-9
          eval(msg)#报错
      
      
      #hash:获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。hash只能操作不可变数据类型。
          print(hash(12322))
          print(hash('123'))
          print(hash('arg'))
          print(hash('alex'))
          print(hash(True))
          print(hash(False))
          print(hash((1, 2, 3)))
          print(hash('fsjkdafsda'))
      
      
      
      #help:函数用于查看函数或模块用途的详细说明。
      
          print(help(list))
          print(help(str.split))
      
          s1 = 'fjdsls'
          print(help(str))
          print(help(str.upper))
      
          s1 = 'sfsda'
          s1.upper()
      
      #callable:函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。
          name = 'alex'
          def func():
              pass
          print(callable(name))  # False
          print(callable(func))  # True
      
      #int:函数用于将一个字符串或数字转换为整型。
          print(int())  # 0
          print(int('12'))  # 12
          print(int(3.6))  # 3
          print(int('0100', base=2))  # 将2进制的 0100 转化成十进制。结果为 4
      
      #float:函数用于将整数和字符串转换成浮点数。
         print(float(3))  # 3.0
      
      #complex:函数用于创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。
         print(complex(1, 2))  # (1+2j)
      
      #bin:将十进制转换成二进制并返回。
      
      #oct:将十进制转化成八进制字符串并返回。
      
      #hex:将十进制转化成十六进制字符串并返回。
          print(bin(10), type(bin(10)))  # 0b1010 <class 'str'>
          print(oct(10), type(oct(10)))  # 0o12 <class 'str'>
          print(hex(10), type(hex(10)))  # 0xa <class 'str'>
      
      #divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。
      
      #round:保留浮点数的小数位数,默认保留整数。
      
      #pow:求x ** y次幂。(三个参数为x ** y的结果对z取余)
          print(divmod(7, 2))  # (3, 1)
          print(round(7 / 3, 2))  # 2.33
          print(round(7 / 3))  # 2
          print(round(3.32567, 3))  # 3.326
          print(pow(2, 3))  # 两个参数为2**3次幂
          print(pow(2, 3, 3))  # 三个参数为2**3次幂,对3取余。
      
      #bytes:用于不同编码之间的转化。
      
          s = '你好'
          bs = s.encode('utf-8')
          print(bs)
          s1 = bs.decode('utf-8')
          print(s1)
          bs = bytes(s,encoding='utf-8')
          print(bs)
          b = '你好'.encode('gbk')
          b1 = b.decode('gbk')
          print(b1.encode('utf-8'))
      
      
      # ord 输入字符找该字符编码的位置
          print(ord('a'))
          print(ord('中'))
      
      # chr 输入位置数字找出其对应的字符
          print(chr(97))
          print(chr(20013))
      
      #repr: 返回一个对象的string形式(原形毕露)。
      
      # %r  原封不动的写出来
          name = 'taibai'
          print('我叫%r'%name)
      
      # repr 原形毕露
          print(repr('{"name":"alex"}'))
          print('{"name":"alex"}')
      
      # all  可迭代对象中,全都是True才是True
      # any  可迭代对象中,有一个True 就是True
          print(all([1,2,True,0]))
          print(any([1,'',0]))
      
      
  3. 总结

    1. 生成器:***
    2. 生成器函数 yield
    3. yield与return 区别。yield from
    4. 列表推导式,生成器表达式。 ***
    5. 内置函数:内置函数
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄