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