zoukankan      html  css  js  c++  java
  • 第八章 迭代器&生成器

    一、迭代器
    迭代是Python最强大的功能之一,是访问集合元素的一种方式。
    迭代器是一个可以记住遍历的位置的对象
    迭代器对象从集合的第一个元素开始访问,知道所有的元素访问完结束。迭代器只能往前不会后退
    迭代器有两个基本的方法:__item__()和__next__()
    1. dir ()
    用来查看数据类型的数据能够执行那些方法,而得到所有的带'__iter__'可以使用for循环,就是可迭代对象
    print(dir(str))
    E:Anacondapython.exe F:/老男孩python/作业训练/8.10/Train.py
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', 
    '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', 
    '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', 
    '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
    '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', 
    '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 
    'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 
    'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 
    'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 
    'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 
    'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
    
    Process finished with exit code 0
    2. __next__()
    可迭代对象可以使用__iter__()来获取到迭代器,而在迭代器中有__next__()
    s = "这是一个可迭代对象"
    it = s.__iter__()   # 获取迭代器
    print(dir(it))  # 迭代器里有__iter__ 还有__next__
    E:Anacondapython.exe F:/作业训练/8.10/Train.py
    ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
    '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__',
    '
    __le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__',
    '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__',
    '__subclasshook__'] Process finished with exit code 0
    3.特点:
    - 只能向前
    只能向下一步进行,不能将之前的结果重新获取
    - 几乎不占用内存
    只有需要的时候,他才给出运行
    - for循环
    # 迭代器模拟for 循环
    lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    for el in lst:  # 底层用的就是迭代器
        print(el)
        
    it = lst.__iter__() # 获取迭代器
    while 1:
        try:    # 尝试执行
            el = it.__next__()  # 获取下一个元素
            print(el)
        except StopIteration:   # 处理错误
            break    # 当执行到最后的时候跳出
    - 惰性机制
    每执行一次'__next()',才给出一个结果,不执行就不给
    s = "这是一个可迭代对象"
    it = s.__iter__()   # 获取迭代器
    print(it.__next__())    # "这"
    print(it.__next__())    # "是"
    print(it.__next__())    # "一"
    print(it.__next__())    # "个"
    print(it.__next__())    # "可"
    print(it.__next__())    # "迭"
    print(it.__next__())    # "代"
    print(it.__next__())    # "对"
    print(it.__next__())    # "像"
    print(it.__next__())    # 超出了迭代范围会报错    "print(it.__next__())  StopIteration"
    4. 如何判断
    from collections import Iterable # 可迭代对象
    from collections import Iterator # 迭代器
    
    lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    it = lst.__iter__() # 获取迭代器
    print(isinstance(lst, Iterable))    # True 为可迭代对象
    print(isinstance(lst, Iterator))    # False 不为迭代器
    print(isinstance(it, Iterable))     # True
    print(isinstance(it, Iterable))     # True
    
    # 偏方
    print("__iter__" in dir(it))    # T
    print("__n__" in dir(it))    # F
    5. list()
    list(参数)把参数进行循环迭代
    lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    it = lst.__iter__()
    s = list(it)
    print(s)    # [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    此处的list如果问set 则输出的就是一个集合,其他如tuple等相同
     
    我们可以把要迭代的内容当成子弹,然后呢获取到迭代器"__iter__()",就把子弹都装在弹夹中,然后发射就是“__next__”把每一个子弹(元素)打出来,也就是说:for 循环的时候,一开始的时候是"__"来
    获取迭代器,后面每次获取元素都是通过"__next__()"来完成的,当程序遇到Stoplteration将结束循环.
    二、生成器
    生成器的本质就是迭代器
    在Python中,使用了yield的函数被称为生成器(generatoor)
    生成器一般由生成器函数或者生成器表达式来创建
    跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单理解生成器就是一个迭代器
    在调用生成器允许的过程中,每次遇到 yield 时函数会暂时保存当前所有的运行信息,返回 yiled 的值,并在下一次执行next()方法时从当前的位置继续运行
    调用一个生成器函数,默认不会执行函数体,返回的是一个迭代器对象
    def func():
        print("哇哈哈")
        yield 1 # return和yiled都能返回数据
        print("呵呵呵")
    
    gen = func()
    
    # 函数中如果有yield 这个函数就是生成器函数,生成器函数生成的是生成器,这个时候不执行函数
    # yield:相当于return可以返回数据,但是yield不会彻底中断函数。分段执行
    gen.__next__()  # 执行函数,执行到下一个yield
    gen.__next__()  # 继续执行到下一个yield 如果没有则会报错    gen.__next__() StopIteration
    1. 生成器的作用
    举例需求:
    当商店需要1W套学士服以备后面的使用:
    def cloth():
        lst = []
        for i in range(0, 10000):
            lst.append("衣服"+str(i))
        return lst
    cl = cloth()
    这样的结果是生产商一次将1W套学士服都给商家,商家不一次性全部卖出的话就会堆积仓库,最好的方式就是商家要一套,生产商给一套,一共1W套:
    def cloth():
        for i in range(0, 10000):
            yield "衣服"+(i)
    cl = cloth()
    print(cl.__next__())
    print(cl.__next__())
    print(cl.__next__())
    区别是:第一种是直接一次性全部拿出来,会很占内存。第二种使用生成器,一次就用一个。用多少生成多少,生成器是一个一个的指向下一个。不会回去,__next__()到哪里,指针就指到哪里.下一次继续获取指针指向的值.
    由此我们可以反应出生成器的那几个特点:
    - 惰性机制
    - 节省内存
    - 只能向前
    2. send()函数
    同__next__()一样都可以让生成器执行到下一个yied。
    # send 函数
    def num():
        print("1")
        a = yield "2"
        print("a=", a)
        b = yield "3"
        print("b = ", b)
        c = yield "4"
        print("c = ", c)
        yield "END"
    gen = num()     # 获取生成器
    ret1 = gen.__next__()
    print(ret1)
    ret2 = gen.send("5")
    print(ret2)
    ret3 = gen.send("6")
    print(ret3)
    ret4 = gen.send("7")
    print(ret4)
    
    E:Anacondapython.exe F:/训练/8.13/Train.py
    1
    2
    a= 5
    3
    b =  6
    4
    c =  7
    END
    send和__next__()区别:
    - send和__next__()都是让生成器向下走一次
    - send可以给上一个yield的位置传递值,不能给最后一个yield发送值,在第一次执行生成器代码的时候哦不能使用send()
    3. 循环:
    生成器可以使用for循环来循环获取内部的元素:
    def func():
        print("1")
        yield "2"
        print("3")
        yield "4"
        print("5")
        yield "6"
        print("7")
        yield "8"
    
    gen = func()
    for i in gen:
        print(i)
     
  • 相关阅读:
    [日常工作] cmd以及bash 直接使用当前目录的方法
    [安全] 公司局域网病毒处理
    SQLserver 使用网络驱动器恢复数据库
    MiniDP与HDMI的关系
    Win10删除微软拼音输入法的方法
    SQLSERVER case when 的学习
    [日常工作]偷懒创建一个存储过程进行模拟工作.
    oracle 18c centos7 设置开机自动启动Oracle
    kali linux升级
    [日常工作]Oracle新增数据文件的小知识点
  • 原文地址:https://www.cnblogs.com/jiumo/p/9457582.html
Copyright © 2011-2022 走看看