• 生成器表达式、集合解析式、字典解析式


    生成器表达式

    生成器的语法为:(返回值 for 元素 in 可迭代对象 if 条件) ,它就是将列表解析式的中括号换成小括号就行了 。它返回的是一个可迭代的生成器对象。

    (x for x in range(1,5))
    
    结果为:
    <generator object <genexpr> at 0x03F3F1B0>

    生成器和列表解析式的区别 

    生成器表达式是按需计算(或称惰性求值、延迟计算),需要的时候才计算值,而列表解析式是立即返回值。

    生成器是一个迭代器,也是可迭代对象。

    #延迟计算,返回迭代器,可以迭代, 从前到后走完一遍后,不能回头
    g = ("{:04}".format(i) for i in range(1,11))
    
    print(next(g))
    for x in g:
        print(x)
    print('~~~~~~~~~~~~')
    for x in g:
        print(x)
    
    结果为:
    0001
    0002
    0003
    0004
    0005
    0006
    0007
    0008
    0009
    0010
    ~~~~~~~~~~~~
    
    #立即计算,返回的不是迭代器,返回可迭代对象列表,从前到后走完一遍后,可以重新回头迭代
     
    g = ["{:04}".format(i) for i in range(1,11)]
    for x in g:
        print(x)
    print('~~~~~~~~~~~~')
    for x in g:
        print(x)
    
    结果为:
    
    0001
    0002
    0003
    0004
    0005
    0006
    0007
    0008
    0009
    0010
    ~~~~~~~~~~~~
    0001
    0002
    0003
    0004
    0005
    0006
    0007
    0008
    0009
    0010

    比如it = (print("{}".format(i+1)) for i in range(2))
    first = next(it)
    second = next(it)
    val = first + second
    val的值是什么? 答案是不能相加
    val = first + second 语句之后能否再次next(it)? 不能再next

    it = (print("{}".format(i+1)) for i in range(2))#IT是生成器
    first = next(it)
    second = next(it)
    val = first + second
    
    结果为:
    1
    2
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-175-9bc925c5dd92> in <module>
          2 first = next(it)
          3 second = next(it)
    ----> 4 val = first + second
    
    TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
    
    
    next(it)
    
    结果为:
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    <ipython-input-176-bc1ab118995a> in <module>
    ----> 1 next(it)
    
    StopIteration: 

    it = (x for x in range(10) if x % 2)
    first = next(it)
    second = next(it)
    val = first + second
    val的值是什么?4
    val = first + second 语句之后能否再次next(it)? 能

    it = (x for x in range(10) if x % 2)
    first = next(it)
    print(first)
    second = next(it)
    print(second)
    val = first + second
    print(val)
    an = next(it)
    print(an)
    
    结果为:
    1
    3
    4
    5

    生成器表达式和列表解析式对比

    计算方式生成器表达式延迟计算,列表解析式立即计算

    内存占用:单从返回值本身来说,生成器表达式省内存,列表解析式返回新的列表。生成器没有数据,内存占用极少,但是使用的时候,虽然一个个返回数据,但是合起来占用的内存也差不多。列表解析式构造新的列表需要占用内存。

    计算速度:单看计算时间看,生成器表达式耗时非常短,列表解析式耗时长,但是生成器本身并没有返回任何值,只返回了一个生成器对象,列表解析式构造并返回了一个新的列表 。

    集合解析式 

    集合解析式的语法: {返回值 for 元素 in 可迭代对象 if 条件},列表解析式的中括号换成大括号{}就行了,它会立即返回一个集合。

    {(x,x+1) for x in range(10)}
    
    结果为:
    {(0, 1),
     (1, 2),
     (2, 3),
     (3, 4),
     (4, 5),
     (5, 6),
     (6, 7),
     (7, 8),
     (8, 9),
     (9, 10)}
    {[x] for x in range(10)} 
    
    {[x] for x in range(10)} 
    
    结果为:
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-189-5bb81d40d8ae> in <module>
    ----> 1 {[x] for x in range(10)}
    
    <ipython-input-189-5bb81d40d8ae> in <setcomp>(.0)
    ----> 1 {[x] for x in range(10)}
    
    TypeError: unhashable type: 'list'

    字典解析式

    字典解析式的语法:{返回值 for 元素 in 可迭代对象 if 条件},列表解析式的中括号换成大括号{}就行了,使用key:value形式,它会立即返回一个字典。

     {x:(x,x+1) for x in range(10)}
    
    结果为:
    {0: (0, 1),
     1: (1, 2),
     2: (2, 3),
     3: (3, 4),
     4: (4, 5),
     5: (5, 6),
     6: (6, 7),
     7: (7, 8),
     8: (8, 9),
     9: (9, 10)}
    
    {x:[x,x+1] for x in range(10)}
    
    结果为:
    
    {0: [0, 1],
     1: [1, 2],
     2: [2, 3],
     3: [3, 4],
     4: [4, 5],
     5: [5, 6],
     6: [6, 7],
     7: [7, 8],
     8: [8, 9],
     9: [9, 10]}
    
    {(x,):[x,x+1] for x in range(10)}
    
    结果为:
    {(0,): [0, 1],
     (1,): [1, 2],
     (2,): [2, 3],
     (3,): [3, 4],
     (4,): [4, 5],
     (5,): [5, 6],
     (6,): [6, 7],
     (7,): [7, 8],
     (8,): [8, 9],
     (9,): [9, 10]}
    
    
    {[x]:[x,x+1] for x in range(10)} #
    
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-198-5f8fa7594e3f> in <module>
    ----> 1 {[x]:[x,x+1] for x in range(10)} #
    
    <ipython-input-198-5f8fa7594e3f> in <dictcomp>(.0)
    ----> 1 {[x]:[x,x+1] for x in range(10)} #
    
    TypeError: unhashable type: 'list'
    
    {chr(0x41+x):x**2 for x in range(10)}#16进制表示
    
    结果为:
    {'A': 0,
     'B': 1,
     'C': 4,
     'D': 9,
     'E': 16,
     'F': 25,
     'G': 36,
     'H': 49,
     'I': 64,
     'J': 81}
    
    {str(x):y for x in range(3) for y in range(4)} # 输出多少个元素?
    
    结果为:
    {'0': 3, '1': 3, '2': 3}

    ret = {}
      for x in range(3):
        for y in range(4):
          ret[str(x)] = y#后面Y的值会覆盖前面的值
    print(ret)

    结果为:

    {'0': 3, '1': 3, '2': 3}

    总结

    一般来说,应该多应用解析式,简短、高效 ,如果一个解析式非常复杂,难以读懂,要考虑拆解成for循环 ,同时应该注意生成器和迭代器是不同的对象,但都是可迭代对象。

    练习题1:

    比如有一个列表names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']],希望找出里面名字含有两个e的。

    这个用列表推导就会很简单,而不用列表推导就会麻烦一点。

    #不用列表推导式
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
    ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    a = []
    for i in names:
        for j in i:
            if j.count("e")>=2:
                a.append(j)
    print(a)
    
    结果为:
    ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
    #用列表推导式
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
    ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    a = [j for i in names for j in i if j.count("e")>=2]
    print(a)
    
    结果为:
    ['Jefferson', 'Wesley', 'Steven', 'Jennifer']

    下面这个题的输出结果是什么:

    def add(a, b):
        return a + b
    
    def test():
        for r_i in range(4):
            yield r_i
    
    g = test()#g是一个生成器对象
    
    for n in [2, 10]:
        g = (add(n, i) for i in g)
    
    print(list(g))
    
    结果为什么是:
    [20, 21, 22, 23]



  • 相关阅读:
    Win7 usb无法识别,感叹号,没有盘符
    MVMM 中的ViewModel 实现IsLoading进度条
    菜鸟喜欢的C# 入门认识和添加,修改,删除 文件夹 文件 大全(转)
    (转)windows负载平衡
    关于刷新页面和用法.(转)
    bat文件调用dos命令 (dos淘金)
    flash新闻轮转:图片和链接从数据库读取之我见
    dling 624+and 2100ap && wireless card&wifi
    html与css小技巧
    小型系统数据库安全小结
  • 原文地址:https://www.cnblogs.com/xpc51/p/11672491.html
Copyright © 2020-2023  润新知