【python】迭代器&生成器

2020-04-23  本文已影响0人  我写的BUG代码少

B站视频链接

目录

一. 迭代器

1.可迭代协议&迭代器协议(Iterable/Iterator)

2.迭代器的好处

二. 生成器(自己写的迭代器)

1.生成器函数(自己写的函数)

def generator():  #1.定义生成器函数
    print(1)
    yield 'a'

ret = generator() #2.生成器函数调用generator(),并得到返回值(返回值ret是一个生成器) #3.返回的生成器 >>> ret
print(ret)   #>>> <generator object generator at 0x000001BC7CC2A5C8> 说明内部代码未被执行,ret是生成器 
print(ret.__next__()) #ret是生成器(迭代器)含有next方法,可调用__next__()

>>>
1
a

[图片上传失败...(image-eb4702-1587608216353)]

def func():
    for i in range(2000000):
        yield '取值%s'%i

g = func()  #生成器1
g1 = func()  #生成器2(新生成器,与生成器1无关)

#从生成器1取50个
count = 0
for i in g:
    count+=1
    print(i)
    if count >50:
        break

#从生成器2继续取50个(共取100个)
for i in g:
    count+=1
    print(i)
    if count >100:
        break

监听文件输入的例子

def tail(filename):
    f = open(filename, encoding='utf-8')
    while True:
        line = f.readline()
        if line.strip(): #如果line.strip()[去掉回车]不为空
            yield line.strip() #不能用return,用return只能取到第一行
            
g = tail('file')
for i in g:
    if 'python' in i:  #监听过滤/有‘python’就打印,没有就不打印
        print(i)

send()的用法

def generator():
    print(123)
    content = yield 1
    print('=====',content)
    print(456)
    yield 2

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello') #send的效果和next一样
print('***',ret)

>>>
123
*** 1
===== hello
456
*** 2

[图片上传失败...(image-cb1cf0-1587608216353)]

如果yield后还有要执行的代码

def generator():
    print(123)
    content = yield 1
    print('=====',content)
    print(456)
    arg = yield 2
    ''' 代码语句'''
    yield    #这里yield空


g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello') 
print('***',ret)

获取移动平均值

def average():
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num
        count += 1
        avg = sum/count
        

avg_g = average()
avg_g.__next__()
avg1 = avg_g.send(10)
avg1 = avg_g.send(20)
'''......'''
print(avg1)
预激生成器的装饰器
def init(func):
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)
        g.__next__()
        return g
    return inner

@init
def average():
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num
        count += 1
        avg = sum/count
        

avg_g = average()
avg1 = avg_g.send(10)
avg1 = avg_g.send(20)
print(avg1)

[图片上传失败...(image-7007f9-1587608216353)]

yield from

def generator():
    a = 'abchdhb'
    b = '123555'
    for i in a:
        yield i
    for i in b:
        yield i

g = generator()
for i in g:
    print(i)
def generator():
    a = 'abchdhb'
    b = '123555'
    yield from a
    yield from b

g = generator()
for i in g:
    print(i)

2.生成器表达式

#【生成器表达式】
g = (i for i in range(10)) #g是生成器
for i in g:
    print(i)

#【列表表达式】
list = [i for i in range(10)]
for i in list:
    print(i)

面试题

面试题1

def demo():
    for i in range(4):
        yield i

g = demo()

g1 = (i for i in g)
g2 = (i for i in g1)

print(list(g1))
print(list(g2)) #g1的值已经被取完了
>>>
[0, 1, 2, 3]
[]

面试题2: for循环+生成器

def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g = test()

for n in [1,10]:
    g = (add(n,i) for i in g)
'''
n = 1
g = (add(n,i) for i in g) #1
n = 10
g = (add(n,i) for i in g)  #都未执行,直到print语句才执行,这个时候再找g
>>>
n = 1
g = (add(n,i) for i in g)
n = 10
g = (add(n,i) for i in (add(n,i) for i in g)) #这步的g是1.的g
>>>
n = 1
g = (add(n,i) for i in g)
n = 10
g = (add(n,i) for i in (add(n,i) for i in test()))
>>>
n = 1
g = (add(n,i) for i in g)
n = 10
g = (add(n,i) for i in (add(10,i) for i in test())) #i=0,1,2,3
#g = (add(n,i) for i in (10,11,12,13))
#g = (add(10,i) for i in (10,11,12,13))
'''

print(list(g))
>>>
[20, 21, 22, 23]
def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g = test()
for n in [1,10,5]:
    g = (add(n,i) for i in g)
'''
n = 1
g = (add(n,i) for i in test())
n = 10
g = (add(n,i) for i in add(n,i) for i in test())
n = 5
g = (add(n,i) for i in add(n,i) for i in add(n,i) for i in test())
#g = (add(5,i) for i in add(5,i) for i in add(5,i) for i in test())
'''
print(list(g))

识别多个文件中的特殊字段,并返回文件名

import os

def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper

@init
def list_files(target):
    while 1:
        dir_to_search=yield
        for top_dir,dir,files in os.walk(dir_to_search):
            for file in files:
                target.send(os.path.join(top_dir,file))
@init
def opener(target):
    while 1:
        file=yield
        fn=open(file)
        target.send((file,fn))
@init
def cat(target):
    while 1:
        file,fn=yield
        for line in fn:
            target.send((file,line))

@init
def grep(pattern,target):
    while 1:
        file,line=yield
        if pattern in line:
            target.send(file)
@init
def printer():
    while 1:
        file=yield
        if file:
            print(file)

g=list_files(opener(cat(grep('python',printer()))))

g.send('/test1')

协程应用:grep -rl /dir
上一篇 下一篇

猜你喜欢

热点阅读