python进阶学习chapter03(迭代相关)
- 如何实现可迭代对象和迭代器对象
- 如何实现反向迭代
- 如何实现在一个for循环中迭代多个可迭代对象
- 对迭代器进行切片操作
- itertools总结
一、如何实现可迭代对象和迭代器对象
重要概念!!!迭代器,可迭代对象,生成器,很容易绕晕了。
凡是可以使用for进行循环的就是可迭代对象,其中可以通过next方法逐步输出的就是迭代器,生成器的形成有两种:一种是把列表生成式改成(),一种是带有yield语句的。
具体的可以看:http://www.cnblogs.com/alex3714/articles/5765046.html
接下来进入主题:
如何实现一个迭代器?
#实现一个迭代器 from collections import Iterator,Iterable #构造迭代器 class WeatherIterator(Iterator): def __init__(self,cities): self.cities = cities self.index = 0 def getweather(self,city): r = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=' + city) dict_data = r.json()['data']['forecast'][0] return "%s:%s,%s" % (city,dict_data['low'],dict_data['high']) def __next__(self): if self.index == len(self.cities): raise StopIteration city = self.cities[self.index] self.index += 1 return self.getweather(city) class WeatherIterable(Iterable): def __init__(self,cities): self.cities=cities def __iter__(self): return WeatherIterator(self.cities) #生成迭代器对象 weatheriterator = WeatherIterator([u'北京',u'南京',u'上海']) #迭代器对象调用next()方法 # print(weatheriterator.__next__()) # print(weatheriterator.__next__()) # print(weatheriterator.__next__()) for x in weatheriterator: print(x)
Python 的迭代协议需要 _iter_() 方法返回一个实现了 _next_() 方法的迭代器对象。
二、如何实现反向迭代
参考:http://www.cnblogs.com/2bjiujiu/p/7248827.html
问题引入:
实现一个连续的浮点数发生器,FloatRange,根据给定范围(start, end) 和步进值,产生一些列的浮点数,例如:FloatRange(3,4,0.2),将产生下列序列:
正向:3.0 3.2 …… 4.0
反向:4.0 3.8 …… 3.0
实现思路:
方法一、列表翻转(但是改变了原列表)
l = [1, 2, 3, 4, 5, 6] l.reverse() for i in l: print(i)
方法二、列表切片(但是得到了和列表等大的列表,浪费空间)
l = [1, 2, 3, 4, 5, 6] for i in l[::-1]: print(i)
方法三、reversed()函数,返回一个反转的迭代器
l = [1, 2, 3, 4, 5, 6] for i in reversed(l): print(i)
for循环是调用的_iter_方法,反向迭代调用的是_reversed_方法
class FloatRange(object): def __init__(self, start, end, step): self.dot = self.__get_dot_num(step) # 有多少个小数点就乘以10的多少次幂,因为浮点数运算不准确,换算成整形数进行计算 self.start = start*pow(10, self.dot) self.end = end*pow(10, self.dot) self.step = step*pow(10, self.dot) def __get_dot_num(self, step): # 计算step有多少个小数点 if isinstance(step, int): return step else: # 通过round实现计算有多少位小数,首创 for dot in range(len(str(step))+1): if step == round(step, dot): return dot def __iter__(self): # 正向迭代 while self.start <= self.end: yield self.start/pow(10, self.dot) self.start += self.step def __reversed__(self): # 反向迭代 while self.end >= self.start: yield self.end/pow(10,self.dot) self.end -= self.step if __name__ == '__main__': float_num_1 = FloatRange(2, 5, 0.1) float_num_2 = FloatRange(2, 5, 0.1) # 正向迭代 for i in float_num_1: print(i) print('_'*60) # 反向迭代 for x in reversed(float_num_2): print(x)
三、如何实现在一个for循环中迭代多个可迭代对象
问题引入:
1、如何同时迭代三个列表(并行):某班期末考试成绩分别存在语文、数学、英语三个列表中,计算每个学生的总分
2、如何依次迭代三个列表(串行):四个班级的英语成绩分别存在四个列表中,统计四个班高于90分的总人数
问题1、可以通过索引,也可以使用zip函数将三个列表打包成一个元组
from random import randint def get_result(chinese, math, english): total = [] # 循环索引进行取值,毕竟列表等长且成绩对应 for index in range(len(chinese)): total.append(chinese[index] + math[index] + english[index]) return total 或者: def get_result(chinese, math, english): total = [] # 通过zip函数进行迭代,实现同时迭代 3 个对象 for c, m, e in zip(chinese, math, english): print(c, m, e) total.append(c + m + e) return total
问题2、通过itertools中的chain
from random import randint from itertools import chain def get_result(e1, e2, e3): # 通过chain函数进行连续窜行迭代3个列表 for i in chain(e1, e2, e3): print(i)
四、对迭代器进行切片操作
问题引入:如何读取某个文件的100~200行的内容呢
是否可以:
f=open()
f[100:200]
方法一、首先使用readlines()读取全部文件,然后再用切片操作,但是文件很大的时候就不适用
f = open() f_all = f.readlines() for i in f_all[100:200]: print(i)
方法二、使用itertools的islice方法
f = open() f_need = islice(f, 100, 200) for i in f_need: print(i)
五、itertools模块的总结
参见廖雪峰官网