• python全栈学习--day13(迭代器,生成器)


    一迭代器

    python一切皆对象

    能被for循环的对象就是可迭代对象。

    可迭代对象:str, list, tuple, dict, set , range

    迭代器:f1文件句柄

    dir打印该对象的所有操作方法:

    s = 'python'
    print(dir(s))
    

      执行输出:

    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__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']

    什么是可迭代对象:内部含有__iter__方法的对象就叫可迭代对象,可迭代对象就遵循可迭代协议。

    如何判断两种方式:

    第一种:

    s = 'python'
    print('__iter__' in dir(s))
    

     

    执行输出:

    True

    第二种:

    from collections import Iterable  #此模块判断是否为可迭代对象
    l = [1,2,3,4]
    print(isinstance(l,Iterable))
    

     

    执行输出:

    True

    from collections import Iterable
    l = [1, 2, 3, 4]
    print(type(l))
    print(isinstance(l,list)
    

      

    执行输出:

    <class 'list'>
    True

     type只能判断是什么类型

    isinstance判断方面更广,不仅能判断类型,还能判断是是否可迭代

    迭代器

    可迭代对象转化成迭代器:可迭代对象.__iter__()-->迭代器

    迭代器不仅含有__iter__,还含有__next__.遵循迭代器协议。

    l1 = [1,2,3]
    l1_ojb = l1.__iter__() #迭代器
    print(l1_ojb)
    

    执行输出:

    <list_iterator object at 0x000001987D5EB668>

    表示它是一个列表迭代器对象

    l1 = [1,2,3]
    l1_obj = l1.__iter__()#迭代器
    print('__iter__' in dir(l1_obj)) #是否含有__iter__方法
    print('__next__' in dir(l1))     #是否含有__next__方法 这里是dir 里给的是 l1这个列表。而不是l1_obj
    print('__next__' in dir(l1_obj))
    

      

    执行输出:

    True
    False
    True

    从结果中,可以看出l1_obj是同时含有__iter__和__next__的对象,所以它是迭代器

    迭代器使用__next__获取一个值

    l1 = [1,2,3]
    l1_obj = l1.__iter__()  # 迭代器
    print(l1_obj.__next__()) #获取一个元素
    print(l1_obj.__next__())
    print(l1_obj.__next__())
    print(l1_obj.__next__())
    

      

    执行报错:

    1
    Traceback (most recent call last):
    2
    3
    File "E:/python_script/day13/迭代器.py", line 9, in <module>
    print(l1_obj.__next__())
    StopIteration

    多取了一个,就会报错,因为列表只有3个元素

    使用for循环方式

    l1 = [1,2,3]
    l1_ojb = l1.__iter__()  #转换为迭代器
    for i in l1_ojb:
        print(i)
    

      执行输出:

    1
    2
    3

    for循环的内部机制,就是使用__next__方法执行的。为什么没有报错呢?它内部有异常处理机制。

    总结:

    仅含有__iter__方法的,就是可迭代对象

    包含__iter__和__next__方法的,就是迭代器

    判断迭代器的2种方法:

    第一种:

    l1 = [1,2,3]
    l1_ojb = l1.__iter__()#转换为迭代器
    print('__iter__' in dir(l1_ojb))
    

      第二种:

    l1 = [1,2,3]
    l1_obj = l1.__iter__()
    from collections import Iterable
    print(isinstance(l1_obj,Iterable))
    

      返回True,就表示它是的

    迭代器的好处:

    1.节省内存空间。

    2.满足惰性机制。

    3.不能反复取值,不可逆。

     不可逆,表示,已经取过值,不能再次取,他只能取下一个。

    for处理机制

    l2 = [1,2,3,4,5,6,7,8]
    for i in l2:
        print(i)
    

    1.将可迭代对象转化成迭代器

    2.内部使用了__next__方法取值

    3.运用了异常处理去处理报错

    迭代器的好处,就是节省内存空间

    好的程序员,会在内存优化化方面考虑,比如迭代器

    使用while循环,指定用__next__方法遍历列表

    l2 = [1,2,3,4,5,6,7,8]
    l2_obj = l2.__iter__()  #1.将可迭代对象转化成迭代器
    while True:
        try:
            i = l2_obj.__next__()  #内部使用__next__方法取值
            print(i)
        except Exception:   #运用了异常去处理报错
            break
    

      try 里面的代码,出现报错,不会提示红色文字。

      Exception 可以接收所有报错,表示报错的时候,该怎么处理,这里直接使用break跳出循环

    面试题:

    使用while循环去遍历一个有限对象

    直接使用上述代码即可。

    二,生成器

    生成器:生成器本质上就是迭代器

    l = [1,2,3]
    l.__iter__()
    

      

    #生成器的产生方式:

    1.生成器函数构造

    2.生成器推到式构造

    3.数据类型转化

    1
    2
    3
    4
    5
    6
    def func1():
        print(111)
        print(222)
        print(333)
        return 666
    print(func1())

    执行输出:

    111
    222
    333
    666

     将函数装换为生成器

    def func1():
        print(111)
        print(222)
        print(333)
        yield 666
    g = func1()
    print(g)
    

      执行输出:

    <generator object func1 at 0x0000023C67C2C3B8>

    第一:函数只要有yield那他就不是一个函数,而是一个生成器

    第二:g称作生成器对象。

    迭代器,使用__next__取值

    def func1():
        print(111)
        print(222)
        print(333)
        yield 666
    g = func1()
    print(g.__next__())
    print(g.__next__())
    

      执行报错
    一个__netxt__对应一个yield。而这里多了一个

    案例:

    生成10000套服装

    一个厂商直接生产出10000套了

    def func1():
        for i in range(1,10001):
            print('Selected服装%d' % i)
    func1()
    

      执行后输出:

    Selected服装1

    。。。。。。

    。。。。。。

    Selected服装10000

    我先生产50套给你

    def func1():
        for i in range(1,10001):
            yield 'Selected服装%d套'% i
    g = func1()
    for i in range(1,51):   #我先生产 50套
        print(g.__next__())
    

     

      执行后输出:

    Selected服装1

    。。。。。。

    。。。。。。

    Selected服装50

    最终老板只要200套
    先50套,再150套

    def func1():
        for i in range(1,10001):
            yield 'Selected服装%d套' % i
    g = func1()
    #先给你生产50套,待后续谈妥善后在给你生产150套
    for i in range(1,51):
        print(g.__next__())
    for j in range(150):
        print(g.__next__())

      执行后输出:

    Selected服装1

    。。。。。。

    。。。。。。

    Selected服装200

     

    对于列表而言,for循环是从0开始的。

    对于生成器而言,它是由指针的,__next__一次,指针向前一次。它不能从头开始。
    必须依次执行才行

    生成器和迭代器的区别

    迭代器:有内置方法

    生成器:开发者自定义

    send

    def generator():
        print(123)
        content = yield 1
        print('=====',content)
        print(456)
        print('***',ret)
        yield
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret=g.send('hello')
    print('***',ret)
    

      

    123
    *** 1
    ===== hello
    456
    *** 1
    *** None

    send 获取下一个值的效果和next基本一致

    只是在获取下一个值的时候,给上一个yield的位置传递一个数据

    使用send的注意事项:

      第一次使用生成器的时候 是用next获取下一个值

      最后一个yield不能接受外部的值。

    next和send功能一样,都是执行一次

    send可以给上一个yield赋值。

    默写内容:

    1.什么是可迭代对象,什么是迭代器

    答:

    内部含有__iter__方法的对象就叫做迭代对象。

    内部必须有__iter__方法和__next__方法的对象,叫做迭代器。

    2.可迭代对象如何转化成迭代器

    答、:

    转化成迭代器:可迭代对象.__iter__()-->迭代器

    例如:

    l1 = [1,2,3]
    l1_obj = l1.__iter__()
    

    3.迭代器如何取值

    迭代器使用__next__()方法

    4.什么是生成器,如何写一个生成器?生成器是怎么取值?

    答:

    生成器,即生成一个容器。在python中,一边循环,一边计算的机制,称之为生成器

    生成器示例:

    1
    2
    def fun1():
        yield 1

      

    生成器使用__next__()方法取值,或者for循环

  • 相关阅读:
    utf8编码和中文不能解码问题解决
    python环境的安装配置
    repo同一个仓的同一个changeId的提交
    Jenkins pipeline之将命令的运行结果赋值给变量
    repo和git常用的命令和场景
    docker 安装rabbitmq
    docker的一些概念
    mysql数据库sql优化原则
    数据库优化02
    MySQL数据库优化总结
  • 原文地址:https://www.cnblogs.com/haowen980/p/8718970.html
Copyright © 2020-2023  润新知