• 迭代器、生成器 DF


    迭代器:

      可迭代对象:要遵守迭代协议,只要有__iter__方法的,就是可迭代对象,可以被for循环

      迭代器:要遵守迭代器的协议,有__iter__和__next__方法的就叫迭代器

          创建一个迭代器 == 可迭代对象.__iter__()

        使用迭代器,就是 == 迭代器.__next__()

    lst = [1,2,3]                (三个获取的都是1)
    l1 = lst.__iter__().__next__()
    l2 = lst.__iter__().__next__()
    l3 = lst.__iter__().__next__()    print(l1),print(l2),print(l3)都是1

    那么换一种方式呢?

    lst = [1,2,3]
    l1 = lst.__iter__()          从一个可迭代对象转化为迭代器
    print(l1.__next__())
    print(l1.__next__())
    print(l1.__next__())          此时输出的结果为1,2,3,如果继续往下再加__next__(),就会报错

     输出可迭代对象的内存地址

    print(str.__iter__('你好'))      <str_iterator object at 0x0000017BF45116D8>
    print(list.__iter__([1,2,3]))    <list_iterator object at 0x0000017BF450B3C8>
    print(dict.__iter__({'1':2}))    <dict_keyiterator object at 0x0000017BF450C4A8>
    print(set.__iter__({1,2,3}))     <set_iterator object at 0x0000017BF45196C0>
    print(tuple.__iter__((1,2,3)))      <tuple_iterator object at 0x0000017BF45116D8>
    print(range.__iter__(range(1,5)))   <range_iterator object at 0x0000017BF4526D70>

     

    生成器定义:

      通俗来说,在函数体中存在yield就是生成器,函数名+小括号就产生了生成器,并且只能向下执行

      函数体中的yield,就是辨别生成器和函数的依据

      生成器的好处就是可以节省空间,一次性完成从上往下执行

    那如何产生一个生成器呢?

    产生一个生成器:
    def
    foo(): print(123) yield 4 print(foo())      结果为,生成器foo的内存地址
    print(foo)       函数foo的内存地址

      那么按照上面这个生成器来看,怎么样才能实现print(123)?

    def foo():
        print(123)
        yield 456
    f = foo()
    print(f.__next__())    这样就实现了print(123),并有返回值456
    print(foo.__next__())   如果把f换成了foo(),就会一直生成新的生成器,会重复打印123,456

    yield的作用:

      yield也可以有返回值,同时也会记录生成器执行到哪里,不会再继续往下执行

      yield可以指定返回值,没有就是None

    现在可以来试着捋一捋生成器的执行流程:

    def foo():             1,定义函数
        print(123)          5,执行
        yield 456           6,返回值456,停止往下执行
        print(789)
        yield 1111
    g = foo()              2,等号右边foo()  3,将foo()赋值给g
    print(g.__next__())        4,g.__next__()

      当有大批量的数据时,用for循环就会占大量的空间,那这时不妨用生成器

    li = []
    def func():
        for i in range(300):
            print(i)
            li.append(i)
    func()
    print(li)
    
    def func():
        for i in range(300):
            yield i
    g = func()
    print(g.__next__())        随取随用,不会过多的开辟空间
    print(next(g))            和g.__next__()效果一样

    yield和next的对应:

      一个.__next__()对应一个yield,如果多了,就会报错

    def func():
        print(1)
        yield 2
        print(3)
        yield 4
        yield 5
        yield 6
    g = func()
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))        最后一个yield下面可以写代码,但是不会执行

    send:发送(在外界向生成器传递参数)

      send == __next__ + 传值(传给上一个yield停住的地方)

    def func():
        print(44)
        l = yield 5          send,将'哈哈'传递给l,
        print(l)
        yield 66
    g = func()        # 生成一个生成器
    print(g.__next__())
    print(g.send('哈哈'))      输出结果为:44,5,哈哈,66

    再来一个

    def func():
        print(44)
        l = yield 5
        print(1)
        yield 66
    g = func()
    print(g.send(None))       输出结果为:44,5

      第一次启动生成器的时候不能用send,但是可以用send(None),这时send的传值功能就取消了,只保留next功能

    所以,第一次启动生成器的时候,  生成器.__next__()  或者  生成器.send(None)

    yield from:

    def func():
        lst = [1,2,3,4,5]
        yield from lst      在这儿实现的就是for循环,for i in lst:print(i)
    g = func()
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())      ps:yield from只能用next

    推导式:  推导式只能走一个分支,但三元运算符可以实现多项

        先写结果,再写语句,如果有筛选,在语句后面添加条件

    列表:

    推导式:
        print([i for i in range(16)])    
    
    展开式:
        li  = []
        def func():
            for i in range(16):
                li.append(i)
        func()
        print(li)

    列表筛选:

    推导式:
        print([i for i in range(10) if i % 3 == 0])
    
    展开式:
        li = []
        def func():
            for i in range(10):
            if i % 3 == 0:
                li.append(i)
        func()
        print(li)

    集合的推导式:

    推导式:    
        dic = {'1':2,'3':4}
        print({i for i in dic.items()})         结果是:({'3':4},{'1':2})或({'1':2}{'3':4})
    筛选:
        print({i for i in range(66) if i > 16})

      集合的推导式和字典很像,但是它只是集合

    字典:

    推导式1:
        lst1 = ['1','2']
        lst2 = [2,3]
        print({lst1[i]:lst2[i] for i in range(2)})     输出结果为{'1':2,'2':3}
    推导式2:
    dic
    = {'1':2,'3':4} print({k:v for k,v in dic.items()})

    生成器的推导式:

    推导式:
        l1 = (i for i in range(1000) 条件)        print(l1),生成器的地址
        for i in range(10):
        print(l1.__next__())
    展开式:
        def func():
          for i in range(100):
               if i % 3 == 0:
              yield i    
        g = func()
        for n in range(10):
          print(g.__next__())
  • 相关阅读:
    HUST第八届程序设计竞赛-G小乐乐打游戏(双bfs)
    HDU-1575-Tr A(矩阵快速幂模板)
    HDU-1061-Rightmost Digit (快速幂模板)
    HihoCoder 1142-三分求极值(三分模板)
    Aizu ITP2_6_A(二分模板)
    Codeforces-938D-Buy a Ticket(最短路设虚拟节点+Dijk优先队列优化)
    POJ-1797-Heavy Transportation(最短路变形)
    HDU-5137-How Many Maos Does the Guanxi Worth(最短路删点)
    POJ-1094-Sorting It All Out (拓扑排序)(判断环和排名是否唯一)
    HDU-1869-六度分离(多源到多源最短路)
  • 原文地址:https://www.cnblogs.com/py8318/p/10262719.html
Copyright © 2020-2023  润新知