• 迭代器和生成器


    一.   迭代器

      1.如何查看一个数据类型的所有方法?

    #dir()可以查看数据类型所有可使用的方法
    print(dir([1,2]))
    print(dir({1,2}))
    print(dir(''))
    
    #结果:
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__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']

           2.通过观察我们不难发现,输出的结果里面都含有 __iter__这个方法(可迭代的都必须含有__iter__方法)

    print('__iter__' in dir([1,2]))
    print('__iter__' in dir({1,2}))
    print('__iter__' in dir(''))
    
    
    
    #结果:
    True
    True
    True

      3.什么是迭代器呢?

        请看下面的例子:

    r=[].__iter__()
    print(r)
    
    
    #结果  : <list_iterator object at 0x000001C90B547358>

      返回乐意个有‘iterator的单词,这是什么意思呢?通过百度我们明白了它就是一个迭代器,

      我们通过调用列表的__iter__方法就得到了一个迭代器。

          4.那我们再看看迭代器里面都含有什么方法

    r=[].__iter__()
    print(dir(r))
    
    
    #['__class__', '__delattr__', '__dir__', '__doc__', 
    '__eq__', '__format__', '__ge__', '__getattribute__',
    '__gt__', '__hash__', '__init__', '__init_subclass__',
    '__iter__', '__le__', '__length_hint__', '__lt__',
    '__ne__', '__new__', '__next__', '__reduce__',
    '__reduce_ex__', '__repr__', '__setattr__', '__setstate__',
    '__sizeof__', '__str__', '__subclasshook__']

      这时我们发现里面有一个‘__next__'方法。那它又有什么用处呢?

    L=[1,2,3,4]
    r=L.__iter__()
    print(r.__next__())
    print(r.__next__())
    print(r.__next__())
    print(r.__next__())
    
    
    
    #1
    #2
    #3
    #4

      每调用一次__next__方法都返回一个L列表里面的值,当列表里面的值输出完时,再调用__next__方法会报错

      5,好了,通过上面的例子我们可以了解到下面知识:

          1.迭代器一定可迭代(必须含有__iter__方法)可迭代不一定就是迭代器

          2.迭代器必定含有__iter__,__next__方法

    二.   生成器

        生成器时在迭代器的基础上形成的(生成器必是迭代器)

       1.生成器函数

    def genteater():
        print('a')
        yield '1'
    
    
    a=genteater()         #a只是一个生成器
    print(a)
    
    
    
    
    #<generator object genteater at 0x0000015792557048>
    
    #generator就是生成器

      那如何打印函数里面的值呢?

    def genteater():
        print('a')
        yield '1'
    
    
    a=genteater()         #a只是一个生成器
    print(a.__next__())   #调用__next__ 方法
    
    #a
    #1

      如果你懂了上面的例子,那么请看下面

    #调用__next__方法,每次只能执行一次yield,再次调用就从上一个yield哪里开始
    def genteater():
        print('a')
        yield '1'
        print('b')
        yield '2'
    
    
    a=genteater()         #a只是一个生成器
    print(a.__next__())   #调用__next__ 方法
    print(a.__next__())   
    
    #a
    #1
    #b
    #2

    #当然我们也可以用for循环的发放循环生成器
    def genteater():
        print('a')
        yield '1'
        print('b')
        yield '2'
    
    
    a=genteater()         #a只是一个生成器
    for i in a:
        print(i)
    
    
    #a
    #1
    #b
    #2
    
    

      2.生成器监听文件的例子:

    #监听文件
    def tail(file):
        f=open(file)
        while True:
            line=f.readline()
            if line.strip():
                yield line.strip()
    
    g=tail('xiaowu')
    for i in g:
        if 'python' in i:
            print('****',i)

     

      send方法(可以向yield传值)

    def generator():
        print('123')
        content=yield 'a'
        print('***',content)
        print('456')
        yield 'b'
    
    g=generator()
    print( g.__next__() )           #  ===print(g.send(None))
    print(g.send('hello'))          #和next用法大致一样,只是可以在获取下一个值的时候给上一个yield的位置传值
                                    #send不能用在开头
    #send实例
    def func(a):
        def inner(*args,**kwargs):
            ret=a(*args,**kwargs)
            ret.__next__()
            return ret
        return inner
    @func
    def avg():
        sum=0
        count=0
        avg=0
        while True:
            num=yield avg
            sum+=num
            count+=1
            avg=sum/count
    
    avg_1=avg()
    ret=avg_1.send(10)
    ret=avg_1.send(2)
    print(ret)

      生成器面试题

           

    #面试题1
    def a():
        for i in range(4):
            yield i
    
    b=a()
    
    b1=(i for i in b)
    b2=(i for i in b1)
    print(list(b1))          #[0,1,2,3]
    print(list(b2))          #[]   (g1已经空了,b2取不到值) 


    #面试题2
    def add(x,y):
        return x+y
    
    def generator():
        for i in range(4):
            yield i
    g=generator()
    
    for a in [1,10]:
        g=(add(a,b) for b in g)
    print(list(g))



    #[20,21,23]
    #其中

    for a in [1,10]:
        g=(add(a,b) for b in g)
    可以被替换成如下:
    a=1
    g=(add(a,b) for b in g)
    a=10
    g=(add(a,b) for b in g) # == g=(add(a,b) for b in (add(a,b) for b in generator() ))




    即可以用下列代码表示
    def add(x,y):
        return x+y
    
    def generator():
        for i in range(4):
            yield i
    g=generator()
    
    a=1
    g=(add(a,b) for b in g)
    a=10
    g=(add(a,b) for b in g)   # == g=(add(a,b) for b in (add(a,b) for b in generator() ))
    print(list(g))
    
    

            

  • 相关阅读:
    jQuery选择器
    asp.net 操作 excel 出现 class 组件错误 或 打开文件错误
    [转]Win7、Windows Server 2008下无法在Windows Service中打开一个已经存在的Excel 2007文件问题的解决方案
    Microsoft Excel 不能访问文件“ 文件名称或路径不存在。 • 文件正被其他程序使用。 • 您正要保存的工作簿与当前打开的工作簿同名。
    页面打印 css
    如何在excel数据透视表的顶部显示列总计
    asp中javascript或jquery如果在body中 且需要页面元素 则需要放在最后
    sqlserver游标使用
    excel 冻结多行
    Request.Form("cardno").Item(y) 的count总是为0
  • 原文地址:https://www.cnblogs.com/wm0217/p/10803330.html
Copyright © 2020-2023  润新知