• python迭代器与生成器


    一、迭代

      1.重复

      2.下一次重复是基于上一次结果

    二、迭代器

      python为了提供一种不依赖于索引的迭代方式,python会为一些对象内置__iter__方法,obj.__iter__称为可迭代的对象,obj.__iter__得到的结果就是迭代器,得到的迭代器既有__iter__,也有一个__next__方法

    d={'a':1,'b':2,'c':3}
    
    i=d.__iter__() #i叫迭代器
    print(i.__next__())

    三、迭代器的优缺点

      1.优点:

        1)提供了一种不依赖于索引的取值方式

        2)惰性计算,节省内存

      2.缺点

        1)取值不如按照索引取值方便

        2)一次性的,只能往后走不能往前推

        3)无法预知长度

    四、生成器

      1.生成器函数:函数体内包含有yield关键字,该函数执行的结果是生成器函数

      2.生成器就是迭代器

    def foo():
        print('first---------->')
        yield 1
        print('second---------->')
        yield 2
        print('third---------->')
        yield 3
        print('fouth---------->')
    
    g=foo()
    
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    yield的功能:
    1.与return类似,都可以返回值,但不一样的地方在于yield返回多次值,而return只能返回一次
    2.为函数封装好了__iter__和__next__方法,吧函数的执行结果做成了迭代器
    3.遵循迭代器的取值方式obj.__next__(),触发函数的执行,函数暂停与再继续的状态都是由yield保存
    def countdown(n):
        print('starting countdown')
        while n > 0:
            yield n
            n-=1
        print('stop countdown')
    g=countdown(5)
    
    for i in g:
        print(i)

      send的效果:

      1.先为暂停位置的yield传一个值,然后yield回吧值赋值给x

      2.与next的功能一样

       yield的表达式形式应用

    #应用:grep -rl 'root' /etc
    import os
    def init(func):
        def wrapper(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return wrapper
    #阶段一:递归地找文件的绝对路径,把路径发给阶段二
    @init
    def search(target):
        'search file abspath'
        while True:
            start_path=yield
            g = os.walk(start_path)
            for par_dir, _, files in g:
                # print(par_dir,files)
                for file in files:
                    file_path = r'%s\%s' % (par_dir, file)
                    target.send(file_path)
    #阶段二:收到文件路径,打开文件获取获取对象,把文件对象发给阶段三
    @init
    def opener(target):
        'get file obj: f=open(filepath)'
        while True:
            file_path=yield
            with open(file_path,encoding='utf-8') as f:
                target.send((file_path,f))
    
    #阶段三:收到文件对象,for循环读取文件的每一行内容,把每一行内容发给阶段四
    @init
    def cat(target):
        'read file'
        while True:
            filepath,f=yield
            for line in f:
                res=target.send((filepath,line))
                if res:
                    break
    
    #阶段四:收到一行内容,判断root是否在这一行中,如果在,则把文件名发给阶段五
    @init
    def grep(target,pattern):
        'grep function'
        tag=False
        while True:
            filepath,line=yield tag #target.send((filepath,line))
            tag=False
            if pattern in line:
                target.send(filepath)
                tag=True
    #阶段五:收到文件名,打印结果
    @init
    def printer():
        'print function'
        while True:
            filename=yield
            print(filename)
    
    start_path1=r'F:python文件day22a'
    start_path2=r'F:python文件day22a'
    g=search(opener(cat(grep(printer(),'root'))))
    
    # print(g)
    # g.send(start_path1)
    g.send(start_path2)
  • 相关阅读:
    32/64位平台printf uint64的方法
    [Linux 安装]centos安装vmware tools
    【Linux】fg bg ctrl + z jobs & 等命令
    让我们慢慢地彼此遗忘
    ctrl+c,ctrl+d,ctrl+z在linux中意义
    Windows 7 右键菜单 添加命令
    修改vs2010所有工程的include目录和lib目录
    Vmware虚拟机的linux与主机共享
    防止atoi函数内存越界
    JavaScriptSerializer使用条件
  • 原文地址:https://www.cnblogs.com/78pikaqiu/p/7041457.html
Copyright © 2020-2023  润新知