# -*- 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()