1. 程式人生 > >python叠代器與生成器

python叠代器與生成器

obj root 賦值 att utf-8 get etc 不能 觸發

一、叠代

  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文件\day22\a\b‘
start_path2=r‘F:\python文件\day22\a‘
g=search(opener(cat(grep(printer(),‘root‘))))

# print(g)
# g.send(start_path1)
g.send(start_path2)

  

python叠代器與生成器