zoukankan      html  css  js  c++  java
  • 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_obj = l1.__iter__()  # 迭代器
    print(l1_obj)

    执行输出:

    <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__方法
    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_obj = l1.__iter__()  # 转换为迭代器
    for i in l1_obj:
        print(i)

    执行输出:

    1
    2
    3

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

    总结:

    仅含有__iter__方法的,就是可迭代对象
    包含__iter__和__next__方法的,就是迭代器

    判断迭代器的2种方法:

    第1种:

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

    第2种:

    l1 = [1,2,3]
    l1_obj = l1.__iter__()  # 转换为迭代器
    from collections import Iterator
    print(isinstance(l1_obj, Iterator))

    返回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 可以接收所有报错,表示报错的时候,该怎么处理,这里直接使用breck跳出循环

    面试题:

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

    直接使用上述代码即可。

    二、生成器

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

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

    #生成器的产生方式:
    1,生成器函数构造。
    2,生成器推导式构造。
    3,数据类型的转化。

    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 0x000001B4C369DE60>

    第一:函数中只要有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('ARMAIN服装%d套' % i)
    func1()

    执行输出:

    ...

    ARMAIN服装9998套
    ARMAIN服装9999套
    ARMAIN服装10000套

    第二个厂商,先生产出50套,给老板看

    def func1():
        for i in range(1,10001):
            yield 'ARMAIN服装%d套' % i
    g = func1()
    for i in range(1,51):
        print(g.__next__())

    执行输出:

    ...

    ARMAIN服装48套
    ARMAIN服装49套
    ARMAIN服装50套

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

    def func1():
        for i in range(1,10001):
            yield 'ARMAIN服装%d套' % i
    g = func1()
    for i in range(1,51):
        print(g.__next__())
    #再执行150次,注意,它是从51开始的
    for j in range(150):
        print(g.__next__())

    之前生产10000套的....

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

    生成器和迭代器的区别
    迭代器: 有内置方法
    生成器: 开发者自定义

    send

    def generator():
        print(123)
        content = yield 1
        print('=======',content)
        print(456)
        yield
     
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret = g.send('hello')   #send的效果和next一样
    print('***',ret)

    执行输出:

    123
    *** 1
    ======= hello
    456
    *** 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中,一边循环,一边计算的机制,称为生成器。

    #生成器示例

    def fun1():
        yield 1

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

  • 相关阅读:
    【JAVA笔记——道】JAVA对象销毁
    【JAVA笔记——道】并发编程CAS算法
    httpClientUtil的get请求
    python基础 day11 下 ORM介绍 sqlalchemy安装 sqlalchemy基本使用 多外键关联 多对多关系 表结构设计作业
    python基础 day11 上 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 事务 索引 python 操作mysql ORM sqlachemy学习
    Python基础 Day10 Gevent协程 SelectPollEpoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 RedisMemcached缓存 Paramiko SSH Twsited网络框架
    python基础 day9 进程、与线程区别 python GIL全局解释器锁 线程 进程
    python基础 day8 Socket语法及相关 SocketServer实现多并发
    python基础 day7 面向对象高级语法部分 异常处理 异常处理 Socket开发基础
    python基础 day6 面向对象的特性:封装、继承、多态 类、方法、
  • 原文地址:https://www.cnblogs.com/tu240302975/p/12654261.html
Copyright © 2011-2022 走看看