• python-列表生成式、生成器、迭代器


    列表生成式

    现在有个需求,[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    要求你把列表里的每个值加1,你怎么实现?
    # 2B青年版
    a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    b = []
    for i in a:
        b.append(i+1)
    print(b)
    a = b
    print('2B', a)
    
    
    # 普通青年版
    a = [1, 3, 4, 6, 7, 7, 8, 9, 11]
    for index, i in enumerate(a):
        a[index] += 1
    print('普通', a)
    #装B青年版
    a = [i+1 for i in range(10)]
    print('装B', a)

    生成器

      现有一个需求:如果创建一个100万个元素的列表,不仅占用很大内存空间,如果我们只用前面几个元素,那么后面绝大多数元素占的空间都白白浪费了。

    1.Python 中,这种一边循环一边计算的机制,称为生成器:generator

    2.Python 中,创建一个列表生成器:只需要吧列表生成式的[]改成()

    a = [i+1 for i in range(10)]   # 列表生式
    print(a)  # 打印列表的值
    
    g = (x*x for x in range(10))   # 列表生成器
    for i in g:
        print(next(g))  # 列表生成器 用next()方法获得

    3.生成器非常强大,如果算法复杂,用列表生成式for循环无法实现的时候,还可以用函数来实现。

    #函数实现斐波拉契数列
    #[1, 1, 2, 3, 5, 8, 13, 21, 34]
    
    
    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            print(b)
            a, b = b, a + b  # t = a + b  ——》a = b  ——》b = t
            n = n + 1
        return 'done'
    
    
    fib(10)
    #函数实现列表生成器
    def fib2(max):
        n, a, b = 0, 0, 1
    
        while n < max:
            #print(b)
            yield b
            a, b = b, a+b
    
            n += 1
    
        return 'done'
    
    
    data = fib2(10)
    print(data.__next__())
    print(data.__next__())
    print("做别的事")
    print(data.__next__())
    print(data.__next__())

    4.要怎样理解generator的执行流程?

      函数:按顺序执行,遇到return语句货最后一行函数语句就返回。

           生成器:每次调用next()的时候执行,遇到yield语句返回,再次被next()调用时,从上次返回的yield语句处继续执行。

    5.上面用next()调用生成器太low,一般用循环+捕获错误来获得返回值。

    #用for 循环调用生成器——发现拿不到返回值。
    for n in fib2(6):
        print(n)
    #如果想要拿到返回值,
    # 必须捕获StopIteration错误,
    # 返回值包含在StopIteration的value中:
    g = fib2(6)
    while True:
        try:
            x = next(g)
            print('g:', x)
        except StopIteration as e:
            print('Generator return value:',e.value)
            break

    迭代器:

      1.直接可以作用于for循环的数据类型有以下几种:

        一类:集合数据类型 ——list、tuple、dict、set、str等;

        一类:generator,包括生成器和带yield的generator 函数

       2.可直接作用于for循环的对象称可迭代对象:Iterable.

      3.可以用isintance()判断一个对象是否是可迭代对象:

    from collections import Iterable
    print(isinstance([], Iterable))       # 列表
    print(isinstance({}, Iterable))       # 字典
    print(isinstance('abc', Iterable))    # 字符串
    print(isinstance((x for x in range(10)), Iterable))  # 生成器
    print(isinstance(100, Iterable))    # 数字

       4.可以被next()调用,并不断返回下一个对象称迭代器:iterator

    from collections import Iterator
    #判断对象是否为迭代器
    print(isinstance([], Iterator))       # 列表
    print(isinstance({}, Iterator))       # 字典
    print(isinstance('abc', Iterator))    # 字符串
    print(isinstance((x for x in range(10)), Iterator))  # 生成器

    说明:列表、字典、字符串这些都不能被next()返回,所以不是迭代器。

         生成器,带函数生成器可以被next()返回,所以是迭代器。

    5.通过iter()函数函数,可以把可迭代对象变成迭代器

    #通过iter()函数把可迭代对象转成迭代器
    print(isinstance(iter([]), Iterator))

     小结:

    1.凡是可以for循环的对象都是——Iterable (可迭代类型)

    2.凡是也可以用于next()的对象都是——iterator(迭代器类型),他们代表一个惰性计算的序列(你调用我,我才生成);

    3.集合数据类型:如list、dict、str等Iterable但不是Iterator,可以通过iter()函数获得一个Iterator对象。

  • 相关阅读:
    vue3 祖孙传递数据
    vue 导航栏不能收缩的问题
    vue 项目中的问题
    Python第一周Round1记录
    [转]80端口被系统占用pid=4: NT kernel & System
    表<表名称> 中的列与现有的主键或UNIQUE约束不匹配
    一些算法(2)
    卸载不了java(tm)se development kit 7 update 3
    如何解决 Eclipse中出现访问限制由于对必需的库XX具有一定限制,因此无法访问类型
    [COPY]Eclipse无法导入项目
  • 原文地址:https://www.cnblogs.com/AYxing/p/8641219.html
Copyright © 2020-2023  润新知