• 迭代器,生成器,列表推导式,生成器表达式



    一、什么是可迭代对象?

    方法一、dir(被测对象),如果他含有__iter__,那这个对象就叫做可迭代对象
     s = "abc"
     print("__iter__" in dir(s))        #True
     print("__iter__" in dir(333))      #False

    遵循可迭代协议

        1.可迭代协议:可以被迭代要满足要求的就叫做可迭代协议。内部实现了__iter__方法

      iterable:可迭代的------对应的标志

      什么叫迭代?:一个一个取值,就像for循环一样取值

           字符串,列表,元组,集合,字典都是可迭代的

        2、迭代器协议:内部实现了__iter__,__next__方法

      迭代器大部分都是在python的内部去使用的,我们直接拿来用就行了

      迭代器的优点:如果用了迭代器,节约内存,方便操作

       dir([1,2].__iter__())是列表迭代器中实现的所有的方法,而dir([1,2])是列表中实现的所有方法,都是以列表的方式返回给我们,为了方便看清楚,我们把他们转换成集合,然后取差集,然而,我们看到列表迭代器中多出了三个方法,那么这三个方法都分别是干什么的呢?

     print(dir([1,2].__iter__()))#查看列表迭代器的所有方法
     print(dir([1,2]))#查看列表的所有方法
     print(set(dir([1,2].__iter__()))-set(dir([1,2])))
      iter_list=[1,2,3,4,5,6].__iter__()
    
      print(iter_list.__length_hint__())#获取迭代器中元素的长度
      print(iter_list.__setstate__(4))#根据索引指定从哪里开始迭代
     
      print(iter_list.__next__())
      print(iter_list.__next__())
      print(iter_list.__next__())#一个一个的取值
      print(next(iter_l))
      next(iter_list)这个方法和iter_list.__next__()方法一样,
      推荐用next(iter_list)这个

    方法二、测试是迭代器还是可迭代对象

    type 只能判断数据类型

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

    from collections import Iterable
    from collections import Iterator

    print(isinstance(l,Iterable)) #True #判断他是可迭代对象
    print(isinstance(l,Iterator)) #False #判断他是迭代器
    print(isinstance(l_iter,Iterator)) #True
    print(isinstance(l,list)) #True

    例子:range 是可迭代对象还是迭代器

    i = range(10)
    # print( "__iter__" in  dir(range(10)))     #True
    # print("__next__" in dir(range(10)))       #False
    
    from collections import Iterable
    from collections import Iterator
    print(isinstance(i,Iterable))      #判断他是可迭代对象
    print(isinstance(i,Iterator))      #判断他是迭代器
    range例子

    二、可迭代对象 iterable 与 迭代器 iterator 有什么关系


    可迭代对象---> 转换成迭代器
    可迭代对象__iter__() --->迭代器

    s = "abc"
    s1 = s.__iter__()
    print(s1)   #<str_iterator object at 0x00000228E73F7278> 遵循得带协议
     li1 = [1,2,3,5]
     print("__iter__" in dir(list))           #True
     
     li2 = li1.__iter__()
     print("__next__" in dir(li2))           #True
    
     print(list2.__next__())
     print(list2.__next__())
     print(list2.__next__())
     print(list2.__next__())

    三、迭代器取值

    只含有__iter__方法的数据是可迭代对象
    含有__iter__方法,并且含有__next__方法的数据是迭代器

    s2 = "abc"
    s3 = s2.__iter__()   #<str_iterator object at 0x00000128D84A7828>
    #
    # print(s3.__next__())
    # print(s3.__next__())
    # print(s3.__next__())
    print("__iter__" in dir(s2))   #True
    print("__next__" in dir(s2))   #False
    print("__iter__" in dir(s3))   #True
    print("__next__" in dir(s3))   #True
    例子1
    l = [1,2,3,4,5]
    print("__iter__" in dir(l))    #True
    print("__next__" in dir(l))    #False
    
    l2 = l.__iter__()
    print(l2.__next__)
    print(l2.__next__)
    print(l2.__next__)
    print(l2.__next__)
    print(l2.__next__)
    例子2

    四、迭代器的意义

    1.迭代器节省内存
    2.迭代器惰性机制
    3,迭代器不能反复,一直向下执行.


    五、for循环的机制.

    内部含有__iter__方法,他会将可迭代对象先转化成迭代器,
    然后在调用__next__方法.
    他有异常处理的方法.

    用while 循环模拟 for 循环机制

     li = [1,2,3]
     li_iter = li.__iter__()
     while True:
         try:                           #遇到错误,try一下
             print(li_iter.__next__())
         except StopIteration:
             break
         有异常处理能力

    总结:
    可迭代对象:str list tuple dict set range
    迭代器: 文件句柄,map


    六、生成器


    (一)生成器的本质是迭代器,生成器是自己用python写的迭代器
    1,可以用生成器函数
    2,可以用各种推导式构建迭代器.
    3,可以通过数据转化.

    (二)

    普通函数

    例子1.1
    def func():
    print(111)
    return 222
    ret = func()
    print(ret)

    生成器函数,生成器
    return yield 区别
    return 返回给调用者值,并结束此函数.
    yiled 返回给调用者值,并将指针停留着当前位置.

    例子1.2
    def gener():
        print("aaa")
        yield 222            #yield是表示是生成器函数
        print("bbb")
        yield 333
        print("ccc")
    g = gener()              #不是执行函数,是产生生成器
    print(g.__next__())      # 一个next,一个yield,并且光标停留在yield后
    print(g.__next__())
    例子2.1:
    def cloth():
        for i in range(100):
            print(i)
    cloth()
    
    例子2.2:
    方法一、
    def cloth():
        for i in range(1000):
            yield "衣服%s"%i
    f = cloth()
    print(f.__next__())     #衣服0
    print(f.__next__())     #衣服1
    
    方法二、
    def cloth():
        for i in range(1000):
            yield "衣服%s"%i
    f = cloth()
    for i in range(50):
        print(f.__next__())
    例子2:range
    (三)面试题

    send
    1.send 和 next 功能一样
    2.给上一个 yiled 整体 发送一个值
    3.获取第一个值的时候,不能用send,只能用next
    可以给上一个yiled整体发送一个值
    def gener():
        print("aaa")
        yield 222
        print("bbb")
        count = yield 333
        print("----->",count)
        yield "aaa"
        yield 333
    g = gener()
    print(g.__next__())
    print(g.send(None))
    print(g.send("AAAA"))
    send例子
    七、列表推导式

    (一)通过数据转换

    list() tuple() 可以将生成器对象转换
    生成器 = 生成器对象


    (二)列表推导式
    [变量(加工后的数据) for  变量 i in 可迭代的数据类型 ] 列表的推导式, 循环模式
    [变量(加工后的数据) for 变量 i in 可迭代的数据类型 if 条件] 列表的推导式, 筛选模式
    li2 = ["python%s期"%i for i in range(1,11)]
    print(li2)

    30以内能被3整除的数的平方

    li1 = [i**2 for i in range(31) if i%3 == 0 ]
    print(li1)
    筛选模式

     

    八、生成器表达式

          类似于列表推倒式,就是把列表推导式的【】改为了()

    l=[{'name':'v1','age':'22'},{'name':'v2'}]
    
    name_list=(dic['name'] for dic in l)        #吧列表生成器的[]改成()
    print(name_list)                            #取出的是一个生成器,而不是要取得值,所以得加上next
    print(next(name_list))
    print(next(name_list))

    九、列表推导式,生成器表达式的作用

    1,列表推导式比较直观,占内存
    2,生成器表达式不容易看出内容,省内存.
    3.python不但使用迭代器协议,
    让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。


    例子1.将一个字典的key 和 value 对调
    前提是value是不可变数据类型,因为键是不可变数据类型
    mcase = {"a" : 10 ,"b" : 34}
    mcasw_frequency = {mcase[k]:k for k in mcase}
    print(mcasw_frequency)
    例子2
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    
     f = [a for i in names for a in i if a.count("e") == 2]
     print(f)
     




  • 相关阅读:
    数据库的接口
    BionicThe README from the bionic/libc
    发现问题——创新的原动力
    使用ADO或ADO控件访问数据库
    游标、事务并发和锁三者之间的那点事
    处女座——菜鸟程序员的工程总结
    数据库的基础知识以及创建数据库
    《Team Geek》前言(中文,自己翻译的)
    万里长征,始于足下——菜鸟程序员的学习总结(一)
    与RMAN相关的动态性能视图
  • 原文地址:https://www.cnblogs.com/lara0520/p/8468040.html
Copyright © 2020-2023  润新知