• Python 函数 IV (生成器等)


    1.今日内容

    1. 生成器初识
    2. 生成器产生方式
    3. yield与return的区别
    4. yield与yield from的区别
    5. send与next的区别
    6. 列表推导式,生成器表达式(字典推导式,集合推导式)
    7. 闭包

    2.具体内容

    1. 生成器初识

      • 生成器本质就是迭代器,python社区中生成器与迭代器是一种概念。生成器与迭代器的唯一区别:迭代器都是python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3]))。生成器是我们自己用python代码构建的工具
    2. 生成器产生方式

      • 生成器函数
      def func():
        print(666)
        yield 2,4,6
        print(888)
        yield 8
      ret = func() #生成器对象
      print(ret) # <generator object func at 0x0000000001E10F68>
      print(next(ret))
      print(next(ret))
      #只要函数中出现yield,那么他就不是函数,它是生成器函数
      #一个next对应一个yield,next超过yield数量会报错,StopIteration
      
      • 生成器表达式
      ret = (i for i in range(3))
      print(ret) #<generator object <genexpr> at 0x10307f0d0>
      #如何触发生成器(迭代器)取值
      #1.next(obj)
      print(next(ret))
      #2.for 循环
      for i in range(3):
        print(next(ret))
      #3.数据转化
      print(list(obj))#[0,1,2]
      
      • python给你提供的一些内置函数,返回一个生成器
      l1 = [1,2,3]
      ret = iter(l1)
      print(next(ret))
      
    3. yield与与return的区别

      • return:结束函数,给函数的执行者返回值(多个值通过元组的形式返回)
      • yield:不结束函数,对应着给next返回值(多个值通过元组的形式返回)
    4. yield 与yield from

      #yield from 的作用
      def func():
        yield from [1,2,3]
      ret = func()
      print(next(ret))#1
      print(next(ret))#2
      print(next(ret))#3
      #yield:对应yield给next返回值
      #yield from:将一个可迭代对象的每一个元素返回给next
      #yield from:节省代码,提升效率(代替for循环)
      
    5. send与next区别

      • 相同点
        • send和next都可以让生成器对应的yield向下执行一次
        • 都可以获取yield生成的值
      • 不同点
        • 第一次获取yield值只能用next,不能用send(可以send(None))
        • send可以给上一个yield传递值
      def func(name):
        print(f'{name} ready to eat')
        while 1:
          food = yield '骨头'
          print(f'{name} start to eat {food}')
      dog = func('将军')
      next(dog)
      #第一次必须用next让指针停留在第一个yield后面不能用shed(send(None))
      #如
      ret = dog.send(None)
      #与next一样,可以获取yield的值
      #还可以给上一个yield发送值
      ret = dog.send('香肠')
      print(ret)
      
    6. 列表推导式,生成器表达式(字典推导式,集合推导式)

      • 列表推导式:一行代码构建一个有规律比较复杂的列表
      #
      l1 = []
      for i in range(5):
        l1.append(i)
      print(l1)
      #列表推导式
      l1 = [i for i in range(1,11)]
      print(l1)
      
      • 两种构建方式

        • 循环模式:[变量(加工后的变量) for 变量 in iterable]
        # 将10以内所有整数的平方写入列表。
        print([i**2 for i in range(1,11)])
        # 100以内所有的偶数写入列表.
        print([i for i in range(2,101,2)])
        # 从包子1期到包子100期写入列表list
        print([f'包子{i}期' for i in range(1,101)])
        
        • 筛选模式:[变量(加工后变量) for 变量 in iterable if 条件]
        # 1-100里大于49的数
        print([i for i in range(1,101) if i > 49])
        # 三十以内可以被三整除的数
        print([i for i in range(1,31) if i %3 == 0])
        # 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
        l1 = ['barry', 'fdsaf', 'alex', 'sb', 'ab']
        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']]
        print(s for i in names for s in i if s.count('e') == 2)
        
      • 列表推导式的优缺点

        简单,快捷;但可读性不高,不好排错

      • 字典推导式,集合推导式

      # 字典推导式,集合推导式:  两种模式: 循环模式,筛选模式
      l1 = ['小潘', '怼怼哥','西门大官人', '小泽ml亚']
      # {0: '小潘', 1: '怼怼哥', 2: '西门大官人'}
      #字典推导式
      print({i:l1[i] for i in range(len(l1))})
      #集合推导式
      print({i for i in range(10)})
      
    7. 闭包

      • 什么是闭包
        • 闭包只能存在嵌套函数中
        • 内层函数对外层函数非全局变量的引用(使用),就会形成闭包
        • 被引用的非全局变量也称自由变量,这个自由变量会与内层函数产生一个绑定关系
        • 自由变量不会在内存中消失
      • 闭包的作用
        • 保证数据的安全
      def func():
        l1  = []
        def inner(s):
          l1.append(s)
          total = sum(l1)
          return total/len(l1)
        return inner
      s = func()
      print(s(100))
      print(s(120))
      print(s(140))
      
      #坑
      def func(a,b):
        def inner():
          print(a)
          print(b)
        return inner
      a = 2
      b = 3
      ret = func(a,b)
      
      #如何判断是闭包
      print(ret.__code__.co_freevars)
      
  • 相关阅读:
    关闭弹出窗体,刷新父页面
    Oracle 导出部分表结构,以及导入
    ORCLE报错解决(ora01747:无效的用户.表.列,表.列)
    PL/SQL Developer使用技巧
    自定义table
    Array查询数组中是否包含指定字符
    水晶报表去掉多余小数点
    HttpHandler HttpModule入门篇
    窗口类名无效 错误 解决方法
    2020.10.15
  • 原文地址:https://www.cnblogs.com/xiaohei-chen/p/11940880.html
Copyright © 2020-2023  润新知