• 资料 迭代器 生成器 协程


    迭代器,python里提供类似装饰器一样的一种语法。

    # 依赖下标循环的方法
    
    l = ['a','b','c','d','e']
    i = 0
    while i < len():
        print(l[i])
        i+=1
    
    # for循环形式迭代
    for i in range(len(l)):
        print(l[i])
    
    

    迭代器

    只要对象本身有__iter__方法,那它就是可迭代的,只要执行这个方法,它的返回值就是迭代器,这个返回值就有个__next__方法.

    dic = {'a':1,'b':2,'c':3}
    i = __iter__(dic)
    print(i.__next__())
    print(i.__next__())
    print(i.__next__())
    print(i.__next__())
    # 当取的值多于元素本身会抛出StopIteration错误,也可以理解为终止信号
    
    # 为避免爆出异常可以这么做
    i = iter(d)
    while True:
        try:
            print(print(next(i))
        excet StopIteration:
            break
            
    # python里面的for循环的方式不是按照下标而是将你传入的对象变成迭代器,去__next__
        
    
    # 在文件中,文件句柄即时迭代器,也是可迭代对象
        
    
    # 为什么要用迭代器
    1.如果像字典,集合,这种无序的又或者文件这种没有索引的,你没有办法像下标那样的取值
    2.迭代器的取值方式是统一的,大家都是按照next的方式取值,迭代器的方式取值占内存比列表这种索引取值更节省内存,他next()一下才会生成一个值属于惰性计算。
    
    # 缺点
    1.迭代器无法统计有多长,只有到最后一步才能知道多长。指定取值的话,必须一步步的取值下去才能取到。所以使用不灵活
    2.迭代器是一次性取值,不能回头。
    
    

    了解就好了哈

    查看可迭代对象

    from collections import Iterable,Iterator
    s = "hello"
    l = [1,2,3]
    t = (1,2,3)
    d = {'a':1}
    set1 = {1,2,3,4}
    f = open('a.txt')
    
    s.__iter__()
    l.__iter__()
    t.__iter__()
    d.__iter__()
    set1.__iter__()
    f.__iter__()
    f.__iter__()
    print(isinstance(s,Iterable))

    生成器

    • 生成器就是一个函数,这个函数内包含有yield这个关键字,生成器是用来生成值的。 生成器也是一种迭代器所以可以 next(g),生成器把函数做成一个迭代器。
    • 生成器与return的区别,return只能执行一次而yield可以执行多次,返回多次值
    • yield 是把函数变成了迭代器,它使函数可迭代,函数也能够拥有yield使用
    from collections import Iterator
    def test():
        print('first')
        yield 1
        yield 2
        yield 3
    
    g= test()
    print(g)    #g是一个函数
    print(isinstance(g,Iterator))    #判断类型
    print(next(g))      
    print(next(g))
    
    
    for i in g:
        print(i)
    
    
    # 生成流程案例
    def test(n):
    print('start')
    while n>0:
        yield n
        n -= 1
    print('done')
    
    g = test(6)
    
    for i in g:
        print(i)
    
    
    
    # 生成器场景案例,模仿tail -f /tmp/a.txt | grep 'error'
    案例1:作用监控文件改变,类似linux下的tail命令。
    import time
    def tail(file_path):
        with open(file_path,'r') as f:
            f.seek(0,2) #移动到最后一行
            while True:
                line = f.readline() 读取当前光标所在位置行。
                if not line:
                    time.sleep(0.3)
                    print('>>>')   #这里打印表示他在一直监控这个文件,程序不是卡死
                    continue
                else:
                    #print(line,end="")
                    yield line
                    
                
    g = tail('a.txt') 
    #print(g.next())
     for line in g:
        print(line)
    
    
    
    import time
    #定义阶段:定义俩生成器函数
    def tail(file_path):
        with open(file_path,'r') as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if not line:
                    time.sleep(0.3)
    #                print('====>')
                    continue
                else:
                    #print(line,end='')
                    yield line
    
    def grep(pattern,lines):
        for line in lines:
            if pattern in line:
                yield line
    
    #调用阶段:得到俩生成器对象
    g1=tail('/tmp/a.txt')
    g2=grep('error',g1)
    
    #next触发执行g2生成器函数
    for i in g2:
        print(i)
    • 协程
      • 协程是用到.send方法,它会去给yield传个值,达到管道的作用,他的作用和next方法相似,但是多了一个传值的步骤
    def eater(name)
        print('%s start to eat food' %(name)
        while True:
            food = yield
            print('%s get %s ,to start eat'%(name,food)
        print('done')
    
    
    name_yield = eater('alex')
    next(e)
    name_yield.send('包子')
    name_yield.send('烧麦')
    name_yield.send('饺子')
    
    
    def eater(name)
        print('%s start to eat food' %(name)
        food_list = []
        while True:
            food = yield food_list
            print('%s get %s ,to start eat'%(name,food)
            food_list.append(food)
        print('done')
    
    
    name_yield = eater('alex')
    next(e)
    name_yield.send('包子')
    name_yield.send('烧麦')
    name_yield.send('饺子')
  • 相关阅读:
    快速理解平衡二叉树、B-tree、B+tree、B*tree
    centos 7(6) linux系统安装 mysql5.7.17(glibc版)
    关于使用Hibernate+spring+dubbo的实现微服务对象查询
    Keepalived+Nginx实现高可用(HA)
    Nginx源码安装
    Keepalived安装与配置
    单点fastDfs+centos7搭建
    Dubbo+zookeeper使用方法以及注意事项
    mac 下 iterm2 不能使用 rz sz
    java 无符号整型
  • 原文地址:https://www.cnblogs.com/alexstraze/p/9233990.html
Copyright © 2020-2023  润新知