zoukankan      html  css  js  c++  java
  • 迭代器、生成器、枚举对象的用法

    def my_generator():
        print(1111)
        yield '结果1'
        print(2222)
        yield '结果2'
        print(3333)
        yield '结果3'
        print(4444)
        yield '结果4'
    g_obj = my_generator()   # my_generator()并不会执行函数体,得到的返回值就是生成器对象,生成器对象就是迭代器对象
    
    r1 = g_obj.__next__()
    print(r1)                # 在函数内部执行一次,在遇到下一个yield时停止,且可以拿到yield的返回值
    r2 = g_obj.__next__()
    print(r2)                # 从上一次停止的位置紧着往下走,在再遇到下一个yield时停止,且可以拿到yield的返回值
    
    
    # 生成器可以被for循环迭代
    
    for v in g_obj:
        print(v)

    一、迭代器概念

    1、迭代器:从装有多个值的容器中一次取出一个值给外界

    ls = [100, 200, 300, 400, 500]    # 被遍历的对象必须是有序容器
    i = 0
    while i < len(ls):
        print(ls[i])
        i += 1
    
    通过迭代器取值优缺点:
        优点:不依赖索引完成取值 
        缺点:不能计算长度,不能指定位置取值(只能从前往后逐一取值)

    2、可迭代对象:该对象有__iter__方法

    有哪些:str、list、tuple、dict、set、range()、file、迭代器对象、enmerate()、生成器

    [].__iter__()().__iter__(){}.__iter__(){}1,}.__iter__()
    
    可迭代对象通过__iter__方法得到迭代器对象

    3、迭代器对象:有__next__方法

    通过该方法获得容器中的值,获取规则,从前往后,一次一个。

    迭代器对象可以做到不依赖索引取值(一次从容器中取出一个值)

    有哪些:file、ensumerate()、生成器 

    从迭代器对象中取元素,取一个少一个,如果要从头开始取,需要重新获得拥有所有元素的迭代器对象

    迭代器对象也有__iter__()方法,调用后得到的是自己本身(当前含有几个元素,得到的就只有几个元素的迭代器对象)

    # 可迭代对象
    ls = [1,2,3,4,5]
    # 迭代器对象
    iter_obj = ls.__iter__()
    print(iter_obj)         # <list_iterator object at 0x00000000021E75C0>
    print([1,2,3,4,5].__iter__())    # 结果为 <list_iterator object at 0x0000000002207780>
    
    
    # 迭代器对象取一个值就少一个值
    ls = [100, 200, 300, 400, 500]
    iter_obj = ls.__iter__()
    print(iter_obj.__next__())     # 100
    print(iter_obj.__next__())     # 200
    print(iter_obj.__next__())     # 300
    print(iter_obj.__next__())     # 400
    print(iter_obj.__next__())     # 500
    # print(iter_obj.__next__())   # 值取完了就抛异常StopIteration,可以通过try对异常捕获并处理
    
    
    # 上一个迭代器对象迭代取值完毕后,就取空了,如果要再次取值,要重新生成迭代器对象
    # iter_obj =ls.__iter__()
    # 迭代器对象不能求长度(内部值的个数)
    ls = [100,200,300,400,500]
    iter_obj = ls.__iter__()
    while True:
        try:
            ele = iter_obj.__next__()
            print(ele)
        except StopIteration:
            print('取完了')
            break

    4、for循环迭代器

    自带异常处理的while循环,自动获取被迭代对象的迭代器对象

    ls = [100,200,300,400,500]
    iter_obj = ls.__iter__()
    for ele in iter_obj:
        print(ele)
    
    for ele in ls:    # 1.自动完成 for ele in st1.__iter__():  2.自动完成异常处理
        print(ele)

    5、总结

    ①可迭代对象:有__iter__()方法的对象,采用该方法可以得到迭代器对象

    ②迭代器对象:有__next__()方法的对象,用该方法可以从可迭代对象中一次获取一个值,取出一个少一个

    ③for循环迭代器:

    自动获取被迭代对象的迭代器对象 

    在内部一次次调用__next__()方法取值

    自动完成异常处理

    obj = [100, 200, 300].__iter__()
    for v in obj:
        print(v)
        if v == 200:
            break
    # 结果为100200
    
    
    obj = [100, 200, 300].__iter__()
    print(obj.__iter__().__iter__().__iter__() is obj)    # True可迭代对象.__iter__()得到的是该对象的迭代器对象迭代器对象.__iter__().__iter__()得到的就是迭代器对象本身

     

    二、生成器

    1、生成器:就是一个迭代器对象

    包含yield关键字的函数就是生成器

    该函数名()得到的是生成器对象,不会执行函数体

    def fn():
        print('我是生成器')
        yield 'god'
    generator_obj = fn()
    print(generator_obj)     # 结果为 <generator object fn at 0x0000000001DF0EB8>
    print(type(generator_obj))    # 结果为 <class 'generator'>
    
    generator_obj.__iter__()      # 可迭代对象
    generator_obj.__next__()      # 迭代器对象

    2、生成器的应用案例:

    当访问的数据资源过大,可以将数据用生成器处理,一次只获取所有内容的一条资源

    def my_range(min,max=0,step=1):
        tag = min
        while True:
            if tag >= max:
                break
            yield tag
            tag += step
    
    range_obj = my_range(5, 10,1 )
    for i in range_obj:
        print(i)

    三、枚举对象

    通过for迭代器,循环遍历可迭代对象,需要知道迭代的索引

    ls = [100, 200, 300, 400, 500]
    count = 0
    for v in ls:
        print(count,v)
        count +=1
    # 结果为0 1001 2002 3003 4004 500
    
    
    ls = [100,200,300,400,500]
    for count, v in enumerate(ls):
        print(count, v)
    # 结果为0 1001 2002 3003 4004 500
  • 相关阅读:
    Android仿人人客户端(v5.7.1)——个人主页(三)
    hdu2554-N对数的排列问题
    POJ1363:Rails
    golang printf
    HDU1200:To and Fro
    [C# 基础知识系列]专题六:泛型基础篇——为什么引入泛型
    poj 2480 (欧拉函数应用)
    Re:从0开始的微服务架构--(二)快速快速体验微服务架构?--转
    爬虫推荐的工具
    python2 与 python3 语法区别--转
  • 原文地址:https://www.cnblogs.com/zhangguosheng1121/p/10651209.html
Copyright © 2011-2022 走看看