资料 迭代器 生成器 协程

迭代器,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('饺子')
原文地址:https://www.cnblogs.com/alexstraze/p/9233990.html