• [Python]推导式与生成器



    推导式可方便生成数据集合,而生成器可返回一个可迭代的对象。

    推导式

    推导式表达式是一种可从一个序列构建另外一个新数据序列的数据处理方式,Python中有三种推导式:列表推导式、字典推导式和集合推导式。

    列表推导式

    列表推导式用于快速生成一个列表:

    [表达式 for 变量 in 可迭代对象] 
    
    [表达式 for 变量 in 可迭代对象 if 条件]
    
    • 1
    • 2
    • 3

    如生成100内偶数列表:
    numbers = [i for i in range(100) if i%2==0]

    字典推导式

    字典推导式用于快速生成一个字典:

    {键:值表达式 for 变量 in 可迭代对象} 
    
    {键:值表达式 for 变量 in 可迭代对象 if 条件}
    
    • 1
    • 2
    • 3

    如快速对换字典的键与值:

    numMap = {1:'one', 2:'two', 3:'three'}
    
    numRev = {v:k for k,v in numMap.items()}
    
    • 1
    • 2
    • 3

    集合推导式

    集合推导式与列表推导式类似,只是外面使用大括号:

    {表达式 for 变量 in 可迭代对象} 
    
    {表达式 for 变量 in 可迭代对象 if 条件}
    
    • 1
    • 2
    • 3

    如获取字符串中字符数:

    s = 'abcdeffsdfsaf'
    
    ch = {x for x in s}
    print(len(ch))
    
    • 1
    • 2
    • 3
    • 4

    生成器

    一边循环一边计算的机制,称为生成器(generator):

    • 生成器能迭代的关键是其有__next__方法:
      • 通过next(g),获取下一个元素;当没有更多元素时,会抛出StopIteration异常;
      • 通过for x in g循环来依次获取生成器中元素;
    • 带有yield的函数不再是普通函数,而是一个生成器:
      • yield类似return返回一个值,但会记住此位置,下次迭代时从下一条语句继续执行;
      • .send()next()类似,但会传递一个值,此值作为yield表达式整体结果返回。

    生成器表达式

    生成器与推导式类似,但生成器表达式占更少的内存,因为:

    • 生成器表达式中的元素是按需逐个生成的;
    • 推导式是一次将所有元素生成,放到内存中。
    (表达式 for 变量 in 可迭代对象)
    
    (表达式 for 变量 in 可迭代对象 if 条件)
    
    • 1
    • 2
    • 3

    也可把生成器转换为其他集合(tuple或list)来获取其全部元素:

    gen = (x**2 for x in range(5))
    print(tuple(gen))
    
    • 1
    • 2

    函数生成器

    通过yield可把普通函数变成生成器:

    def genNum(count=10):
        for n in range(count):
            yield n
    
    num = genNum(5)
    for i in num:
        print(i)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    send

    要使send生效(send的参数为yield的返回值),需要修改yield语句:

    • 获取返回值,然后重设yield的变量;
    • 在调用send前,需要要已调用过next(保证已挂在yield语句处);
     def genNum(count=10):
         i = 0
         while i < count:
             v = (yield i)
             if v:
                 i = v
             else:
                 i += 1
    
     num = genNum()
     print(next(num)) # 0
     print(num.send(3)) # 跳过1、2,返回3
     for i in num:  # 从4开始
         print(i)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可迭代对象

    能够逐一迭代返回元素的对象即为可迭代对象,包括:

    • 所有序列类型:str、list、tuple、range;
    • 非序列集合:set、dict、文件对象(open返回的);
    • 实现了__iter__()方法的任意对象;
    • 实现了__getitem__()方法的任意对象;

    迭代器

    定义了__iter__()(必须返回一个迭代器)方法的对象,就实现了迭代协议;即为一个迭代器:

    • 所有可迭代对象,都可通过iter()方法转换为迭代器:如iter('abcd')
    • 迭代器使用next()进行迭代操作;*
    class GenNumbers:
        def __init__(self, count):
            self.count = count
    
        def __iter__(self):
            self.n = 1
            return self
    
        def __next__(self):
            if self.n <= self.count:
                x = self.n
                self.n += 1
                return x
            else:
                raise StopIteration
    
    gen = GenNumbers(10)
    for i in gen:
        print(i)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    如何应用MBTI职业性格测试来做职业规划
    springboot一个简单的前端响应后端查询项目
    浅谈软件测试面试一些常见的问题
    python基础—面向对象
    基于jenkins+k8s实现devops
    大数据-玩转数据-Flink Sql 窗口
    Spring Retry教程(3)-模板方式的实现
    三菱FX3U PLC S型速度曲线生成FB
    [附源码]java毕业设计保险客户管理系统
    利其器(1)——配置idea快捷键与常用快捷键的使用
  • 原文地址:https://blog.csdn.net/alwaysrun/article/details/126201327