1. 程式人生 > >十一、叠代器、生成器

十一、叠代器、生成器

gen 函數 返回 class gre 超出 新增 true 基礎上

叠代

  叠代是一個重復的過程,每次重復即一次叠代,並且每次叠代的結果都是基於下一次叠代的結果

  如公司軟件:基於第一次基礎上修改,發第二個版本,基於第二個,發第三個。。。

循環
while True:
    name = input(‘名字:‘)
    print(name)

叠代
count = 0
while count<10:
    print(count)
    count+=1

可叠代對象:

  python提供的不依賴索引的叠代方式,會為一些對象內置 __iter__ 方法

  只要有 __iter__ 方法的對象,就是可叠代對象

  可叠代對象有:

字符串
列表
元組
字典
集合
文件對象

  對象執行 __iter__ 方法後,得到的就是叠代器

叠代器

  既有 __iter__ 方法,又有 __next__ 方法

  __next__方法不依賴索引叠代對象,__next__一次叠代一次

  當叠代超出,會提示 StopIteration,沒有這個值

d = {‘a‘:1,‘b‘:2,‘c‘:3,‘d‘:4}
i = d.__iter__()                       # 得到叠代器  i
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())        # StopIteration

  優點:

      1.不依賴索引(統一了叠代方式)

      2.節省內存,惰性計算,同一時間內存只有一個值 (比如讀文件內容,不一下全讀出來,節省內存) 

  缺點:

      1.只能一次性往後next取值

      2.無法獲取長度

for循環與叠代器:

  之前說過字典沒有索引,直接通過 for i in dict 可以取值

  原理就是:

i = d.__iter__()
i.__next()

被循環的對象執行__iter__方法到的 i
i 自動執行__next__
直到報出StopIteration結束,for循環捕捉處理

  所以 for 可以直接循環叠代器:

def func():
    print(1)
    yield  1
    print(2)
    yield   None
    print(3)
    yield         #這裏不加yield,報StopIteration
g = func().__iter__()
for i in g:
    print(i)            #  1  None  None  

  


生成器 

  生成器函數

    函數體包含 yield 關鍵字,這個函數執行的結果就是生成器

    yeild 將函數做成了生成器,遵循叠代器的取值方式

def func():
    print(‘真‘)
    yield
    print(‘帥‘)
g = func()
print(g)             # <generator object func at 0x00000214686B6990>

  生成器也具有 __iter__ 和 __next__ 方法,實際生成器就是叠代器:

l = [1,2,3,4,5]
b = l.__iter__()
print(b.__next__())         #  觸發一次叠代列表操作,取一次值就結束

def func():
    print(‘真‘)
    yield
    print(‘帥‘)
g = func()
g.__next__()            # 觸發一次函數的執行,函數的結束標準是 return 這裏的 yield 就相當於 return 的終止執行操作


def func():
    print(1)
    yield  1
    print(2)
    yield   None
    print(3)
    yield         #這裏不加yield,報StopIteration
g = func()
g.__next__()
g.__next__()
g.__next__()
# 碰到yield 就暫停,返回值,然後再執行next,函數繼續從暫停位置執行,依次類推;
# 如果函數執行最後沒有返回值,就報StopIteration
# 與 return 的區別:     1.可以返回多次值,return只能1次
#                       2.保存執行狀態,繼續向下執行,return執行就終止函數

模擬linux中 tail -f 命令(動態查看文件新增的一行內容):

  分析:

    1.一次讀一行:readline

    2.最新一行:光標要在每行的最後位置

    3.循環上兩步操作

    4.讀到內容返回,沒讀到重新進入循環

import time
def tail(filepath,encoding=‘utf-8‘):
    with open(filepath,encoding=encoding) as f:
        f.seek(0,2)
        while True:
            line = f.readline()
            if line:
                print(line,end=‘‘)
            else:
                time.sleep(1)
tail(‘a.txt‘)

    增加過濾 tail - f a.txt | grep ‘shuai‘ 過濾出 shuai

import time
def tail(filepath,encoding=‘utf-8‘):
    with open(filepath,encoding=encoding) as f:
        f.seek(0,2)
        while True:
            line = f.readline()
            if line:
                yield line
            else:
                time.sleep(1)
# g = tail(‘a.txt‘)

def grep(lines,item):
    for line in lines:
        if item in line:
            yield line
grep_g = (tail(‘a.txt‘),‘shuai‘)
for i in grep_g:
  print(i)

  | 管道符:左邊的執行結果返回給右邊

再來個

def foo(n):
    while n>0:
        yield n
        n-=1
g = foo(6)
print(g.__next__())     # 6
print(g.__next__())     # 5
for i in g:
    print(i)            # 4 3 2 1

叠代器是一次性的,只能一直往後取,for把剩下的值取了


def foo(n):
    while n>0:
        yield n
        n-=1
g = foo(6)
for i in foo(6):
    print(i)        # 6 5 4 3 2 1
for i in foo(6):
    print(i)        # 6 5 4 3 2 1 


這裏的兩個for 是循環單獨的生成器


def foo(n):
    while n>0:
        yield n
        n-=1
print(foo(6).__next__())        # 6
print(foo(6).__next__())        # 6

這兩次也是操作了兩個生成器

  

十一、叠代器、生成器