Effective Python 讀書筆記: 第17條: 在參數上面迭代時,要多加小心

# -*- encoding: utf-8 -*-

import os

'''
第17條: 在參數上面迭代時,要多加小心

關鍵:
1 迭代器協議
含義:for循環遍歷容器時,需要依靠迭代器寫意
本質: 執行類似for x in data這樣的語句時,python實際會調用iter(data)
內置的iter函數又會調用data.__iter__方法,該方法必須返回迭代器對象。
該迭代器實現了__next__方法。
fox x in data --> iter(data) --> data.__iter__ --> __next__

2 編寫自己的容器
本質: 所謂容器,就是實現了自己的迭代器__iter__方法
步驟: 編寫一個類,給該類實現__iter__方法,用yield返回生成器
樣例:
class ReadData(object):
    def __init__(self, fileName):
        self.fileName = fileName

    def __iter__(self):
        with open(self.fileName, "rb") as fr:
            for line in fr:
                yield int(line)
                
3 總結
成爲容器的方法就是編寫一個類,並重寫這個類的__iter__方法。
判斷某個值是否時迭代器還是容器,就用值作爲參數,兩次調用iter函數,結果相同則爲迭代器。

參考:
Effectiv Python 編寫高質量Python代碼的59個有效方法

'''

class ReadData(object):
    def __init__(self, fileName):
        self.fileName = fileName

    def __iter__(self):
        with open(self.fileName, "rb") as fr:
            for line in fr:
                yield int(line)


def generateFile(fileName, dataList):
    content = "\n".join(dataList)
    with open(fileName, "wb") as fr:
        fr.write(content)


def mynormalize(datas):
    # the input parameter is an iterator, raise error
    if iter(datas) is iter(datas):
        raise TypeError("Must be a container")
    total = sum(datas)
    result = []
    for value in datas:
        percent = 100.0 * value / total
        result.append(percent)
    return result


def process():
    dataList = [str(i) for i in range(4)]
    fileName = "./data.txt"
    generateFile(fileName, dataList)
    datas = ReadData(fileName)
    results = mynormalize(datas)
    print results
    datas = [0, 1, 2, 3]
    results = mynormalize(datas)
    print results
    it = iter(datas)
    results = mynormalize(it)
    print results


if __name__ == "__main__":
    process() 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章