• 迭代器,生成器


    迭代器

    迭代器:迭代的工具。迭代是更新换代,迭代也可以说成是重复,并且每一次的重复都是基于上一次的结果来的。如计算机中的迭代开发,就是基于软件的上一个版本更新。以下代码就不是迭代,它只是单纯的重复。

    # 纯粹的重复
    while True:
        print('我只是一个重复的过程')
    

    可迭代的对象

    可迭代对象:只要具有 _inter_ 方法的数据类型,都是可迭代对象。

    # 字符串
    st = 'zkim'
    print(st.__iter__())
    
    # 列表
    l = [1,2,3]
    print(l.__iter__())
    
    # 元组
    t = (1,2,3)
    print(t.__iter__())
    
    # 字典
    d = {'name':'zkim','age':18}
    print(d.__iter__())
    
    # 集合
    se = {1,2,3}
    print(se.__iter__())
    
    # 文件
    f = open('xxx','w',encoding='utf-8')
    print(f.__iter__())
    f.close()
    
    # <str_iterator object at 0x000000B2AC1EC3C8>
    # <list_iterator object at 0x000000B2AC1EC358>
    # <tuple_iterator object at 0x000000B2AC1EC390>
    # <dict_keyiterator object at 0x000000B2AC1585E8>
    # <set_iterator object at 0x000000B2AC1E9BD0>
    # <_io.TextIOWrapper name='xxx' mode='w' encoding='utf-8'>
    

    可迭代对象使用 _iter_ 的方法,可以拿到一个返回值,这个返回值就是迭代器对象。

    迭代器对象

    数据类型中,字符串,列表,元祖都是依赖索引取值的。在这里我们又学到了一个可以不依赖索引,就能取值的方法。(迭代器对象)

    迭代器对象:既有内置 _inter_ 方法,又有内置 _next_ 方法的数据类型。

    注意:当某一个数据类型中的值,依次被取完之后,如果再取的话就会报错。错误:StopIteration

    # 文件类型的数据既有__iter__,又有__next__,所以文件本身就是迭代器对象。
    f = open('text.txt','r',encoding='utf-8')
    f.__iter__()
    f.__next__()
    
    # 字符串
    st = 'zkim'
    res = st.__iter__()
    print(res.__next__())
    print(res.__next__())
    
    # 列表
    l = [1,2,3]
    res1 = l.__iter__()
    print(res1.__next__())
    print(res1.__next__())
    
    # 元祖
    t = (1,2,3)
    res2 = t.__iter__()
    print(res2.__next__())
    print(res2.__next__())
    
    # 字典
    d = {'name':'zkim','age':18}
    res3 = d.__iter__()
    print(res3.__next__())
    print(res3.__next__())
    
    # 集合
    se = {1,2,3}
    res4 = se.__iter__()
    print(res4.__next__())
    print(res4.__next__())
    
    # z
    # k
    
    # 1
    # 2
    
    # 1
    # 2
    
    # name
    # age
    
    # 1
    # 2
    

    注意:当某一个数据类型中的值,依次被取完之后,如果再取的话就会报错。错误:StopIteration

    l = [1,2]
    res = l.__iter__()
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())
    
    # StopIteration
    

    在上述的方法中没取一个值就得 _next_ 一次,特别的繁琐,所以我们可以用 while 循环来精简下。为了防止报错可以使用异常捕捉: try...except... 来处理

    l = [1,2,3]
    iter_l = l.__iter__()
    while True:
        try:
            print(iter_l.__next__())
    	except StopIteration:
    		break
    
    # 1
    # 2
    # 3
    
    • 总结:

    迭代器对象:执行可迭代对象的 _inter_ 方法,拿到的返回值就是迭代器对象。

    • 特点:

    1:内置 _next_ 方法,执行该方法会拿到迭代器对象中的一个值。

    2:内置有 _iter_ 方法,执行该方法会拿到迭代器对象。

    3:文件本身就是迭代器对象。

    • 优点:

    1:不依赖索引取值。

    2:内存中永远只占一份空间,不会导致内存溢出。

    • 缺点:

    1:取值麻烦,不能获取指定的值,并且只能往后取。

    2:取完之后会报 StopIteration 的错误。

    for 循环内部原理

    for 循环称之为迭代器循环, in 后面接的必须是可迭代对象。

    • for 循环内部的本质:

    1:将 in 后的对象调用 _iter_ 转换成迭代器对象

    2:调用 _next_ 迭代取值

    3:内部有异常捕获 StopIteration,当 _next_ 报这个粗时,会自动结束循环。

    l = [1,2,3]
    for i in l:  
        print(i)
    
    # 1
    # 2
    # 3
    

    生成器

    生成器:用户自定义的迭代器,本质就是迭代器。

    • 关键字 yield

    1:帮你提供了一种自定义生成器的方式。

    2:可以将函数体代码的运行暂停。

    3:可以返回值

    # 自定义的迭代器:生成器,是定义在函数内部的,利用 yield 关键字,将函数自定义成一个生成器
    def func():
        print('我是第一个')
        yield 1
        print('我是第二个')
        yield 2
    g = func()  # 在调用函数的时候,有 yield 的情况下不会执行函数体代码
    print(g.__next__())  # 执行到 yield 1 的时候暂停
    print(g.__next__())  # 执行到 yield 2 的时候暂停
    # 只有在调用的时候才会依次往下执行。
    
    # 我是第一个
    # 1
    # 我是第二个
    # 2
    
    # yield 可以接收外部的值
    def shopping(shop):
        print('%s 已被购买'%shop)
        while True:
            people = yield
            print('%s 被 %s 购买'%(shop,people))
    
    res = shopping('法拉利')
    res.__next__()
    res.send('鸡哥')
    
    # 法拉利 已被购买
    # 法拉利 被 鸡哥 购买 
    
    • 与 return 的异同之处

    相同点:

    都可以返回值,并且都可以返回多个值。

    不同点:

    yield 可以返回多次值,而 return 只能返回一次后函数立即结束。

    yield 还可以接受外部传入的值。

    生成器表达式
    res = (i for i in range(1,3) if i != 4)
    print(res)
    print(res.__next__())
    print(res.__next__())
    
    # <generator object <genexpr> at 0x0000000BA3EAB728>
    # 1
    # 2
    
    千里之行,始于足下。
  • 相关阅读:
    终于有人把 Docker 讲清楚了,万字详解!
    Java 14 可能带来什么新特性?
    我 45 岁还写代码,怎么了?
    傻傻分不清?Integer、new Integer() 和 int 的面试题
    showModalDialog打开页面有缓存,不走action
    ajax,下拉框级联
    jsp中<!DOCTYPE>标签
    struts配置文件中如何从一个package的action跳到另一个package中的某个action
    jsp通过s:hidden传值给后台,后台数据出现了若干逗号问题
    struts2.0整合json
  • 原文地址:https://www.cnblogs.com/jincoco/p/11190629.html
Copyright © 2020-2023  润新知