Python-迭代協議-__iter__ __next__ iter next yield

iterpython

  本質是for循環調用的實質,for循環經過調用這個函數返回可迭代對象生成器形式,開始迭代取值捕獲StopIteration錯誤退出循環dom

  for循環首先找__iter__方法,而後再找 __getitem__方法,若是都沒找到則報錯,對象不是可迭代對象函數

 

__iter__ui

  若是是自定義類生成的對象則iter方法調用__iter__函數, 這個函數必須返回迭代器對象this

 

nextspa

  啓動生成器。並獲取生成器第一個值協程

 

__next__對象

  將對象變成生成器對象,也是 next方法調用對象中__next__方法blog

from random import randint


class BeiMenChuiXue:
    """本身實現的迭代器"""
    def __init__(self, iterable):
        self.iterable = iterable

    def __next__(self):
        for member in self.iterable:
            yield member


class DuGuJiuJiu:
    """可迭代對象"""
    def __init__(self, numbers):
        self.numbers = numbers

    def __iter__(self):
        # 經過全局函數 iter實現
        # return iter(self.numbers)

        # 交給本身實現的迭代器
        return next(BeiMenChuiXue(self.numbers))


if __name__ == '__main__':
    numbers = [randint(-10, 10) for _ in range(10)]
    print(numbers)
    du_gu_jiu_jiu = DuGuJiuJiu(numbers)
    for member in du_gu_jiu_jiu:
        print(member)

  

 北門吹雪: https://www.cnblogs.com/2bjiujiu/three

 

yield

  yield能夠跳出函數並傳出一個值,也能夠傳遞進去一個值被函數內部收到並接着執行函數,相似函數與函數之間造成通訊而且能夠暫停並啓動函數的特性,是協程實現的最底層原理

def bei_men_chui_xue():
    hai = yield "我是 bei_men_chui_xue 函數"
    print(hai)


if __name__ == '__main__':
    bei = bei_men_chui_xue()
    message = bei.send(None)
    print(message)
    try:
        bei.send("我是 main 函數")
    except StopIteration as e:
        pass

  

經驗:

  1. for循環迭代的本質仍是生成器對象,而後捕獲StopIteration自動退出循環

  2. 協程實現的底層原理是yield特性,既能夠暫停函數並傳出一個值也能夠接收一個值從新啓動函數的特性最具備Python語言風格

  3. 迭代結束會自動觸發StopIteration,這個異常是結束信號,須要捕獲這個異常

 

bei_men_chui_xue: https://www.cnblogs.com/2bjiujiu/

 

經過yield讀取大文件思路:

  1. 打開文件得到句柄 open

  2. 經過read方法讀取指定偏移量數據

  3. 定義一個讀生成器,傳遞文件句柄和讀取偏移量

  4. 定義一個buf,循環判斷分隔符是否在buf中,取出分隔符前面的字符(經過切片),yield出去,更新buf分隔符後面的字符

  5. 若是沒有找到分隔符,則read數據,判斷是否讀取完畢,讀取完畢退出,有數據則拼接到buf中

def read_big_file(filename, read_size=20, sep='\n'):
    """讀取大文件"""
    f = open(filename, 'r', encoding='utf-8')
    buf = ''
    sep_len = len(sep)
    while True:
        # 第一層取數據
        data = f.read(read_size)
        # 判斷文件是否讀完
        if data is None:
            raise StopIteration
        buf += data
        while True:
            # 第二層生成數據
            if sep in buf:
                index = buf.index(sep)
                yield buf[:index]
                buf = buf[index + sep_len:]
            else:
                break


if __name__ == '__main__':
    file_name = "python_this.txt"
    read_generator = read_big_file(filename=file_name)
    oneline = next(read_generator)
    twoline = next(read_generator)
    threeline = next(read_generator)
    print(oneline, end='')
    print(twoline, end='')
    print(threeline, end='')
相關文章
相關標籤/搜索