python3:生成器的多次讀取

前言

生成器(generator)可以幫我們在傳遞大量數(shù)據(jù)時節(jié)省內(nèi)存。

一般情況下,生成器只能被讀取一次。

但是總有某種情況下,需要對生成器多次讀取。

本文意在提供一種優(yōu)雅的方式解決此類問題。

環(huán)境

python 3.6

正文

當要對一個生成器多次讀值時,存在多種實現(xiàn),比如 lamda。(印象中似乎有移動指針的方法)

但是這種代碼并不優(yōu)雅。

我們可以實現(xiàn)一個 迭代器協(xié)議的容器類。

這里舉一個例子:
一個文件當中,每一行都存著一個數(shù)字,求出每一行數(shù)字的百分比。為了方便,這里拿一個列表來模擬文件。

詳細代碼如下:

# 生成器讀取文件,這里使用列表模擬文件
def read_file_iter(file):
    # with open ...
    for line in file:
        yield int(line)


# 計算百分比,方法體中讀取了兩次生成器。一次是 sum,一次是 for。生成器在 sum 操作后便已經(jīng)空了。
def cal_percent(numbers):
    total = sum(numbers)
    results = []
    for num in numbers:
        results.append(num / total * 100)
    return results


# 使用容器類實現(xiàn)迭代讀取文件,這里依然使用列表模擬文件,略去打開文件的步驟
class ReadFile():
    def __init__(self, data_path):
        self.data_path = data_path

    # 每次輪詢該對象時,均會生成一個新的生成器
    def __iter__(self):
        # with open ...
        for line in self.data_path:
            yield line


if __name__ == "__main__":
    numbers = [10, 100, 1000]

    # ------------------
    # 在需要對生成器多次讀值時,普通的生成器寫法不再合適。
    # 可以實現(xiàn)一種 迭代器協(xié)議的容器類 來滿足這種需要對生成器多次讀值的要求。
    # 下列 【情況一】 為普通的迭代寫法,【情況二】為實現(xiàn) 迭代器協(xié)議的容器類
    # ------------------

    # 【情況一】:
    # 這里的結(jié)果是空。
    # 因為 read_numbers 是一個生成器。
    # 在 cal_percent 中 sum 方法和 for 循環(huán)均是對該生成器的讀取。而生成器只能被讀取一次
    read_numbers = read_file_iter(numbers)
    results = cal_percent(read_numbers)
    print(results)



    # 【情況二】
    # 這里的結(jié)果是正常的。
    # read_numbers 僅僅是一個不包含實際數(shù)據(jù)的對象
    # 在 cal_percent 中 sum 方法和 for 循環(huán)讀取該對象時,該對象會分別返回兩個獨立的生成器。因此工作正常。
    read_numbers = ReadFile(numbers)
    results = cal_percent(read_numbers)
    print(results)

擴展

參考

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容