可迭代对象与迭代器对象
问题举例
某软件要求,从网络抓取各个城市的气温信息,并依次显示:
北京:15~22
上海:18~23
......
如果一次抓取所有城市气温信息再显示,显示第一个城市的气温时会由很长的延时,
并且浪费存储空间,我们期望以“用时访问”的策略,并且把所有城市的气温信息封装
到一个对象里,可用for语句进行迭代。
for循环工作流程
来个栗子
list1 = [1, 2, 3, 4, 5] for ele in list1: print(ele) it = iter(list1) next(it) next(it) next(it) next(it) next(it) next(it)
for循环中in后面的对象一定为可迭代对象
iter()返回一个可迭代器对象,由可迭代对象生成
next()方法对迭代器对象进行迭代
最后报异常StopIteration
迭代器
迭代器对象为一次性消费,用完不可再生,
如果要使用,需要重新拿到迭代器,
两个迭代器之间无干扰。
栗子
list1 = [1, 2, 3, 4, 5] it1 = iter(list1) print(next(it1)) #1 print(next(it1)) #2 print(" for loop") for x in it1: print(x) #3 #4 #5 print(" No interference between two iters") it2 = iter(list1) it3 = iter(list1) print(next(it2)) #1 print(next(it3)) #1 print(next(it2)) #2 print(next(it3)) #2
迭代器对象是一个可迭代对象又是一个迭代器对象,调用可迭代接口(__iter__)返回它自身。
可迭代对象每次都创建一个迭代器。
解决思路
STEP1:实现一个迭代器对象WeatherIterator,__next__每次返回一个城市的气温信息
STEP2:实现一个可迭代对象WeatherIterable,__iter__方法返回一个WeatherIterator对象
代码:
from collections import Iterable, Iterator import requests class WeatherIterator(Iterator): def __init__(self, cities): self.cities = cities self.index = 0 def __next__(self): if self.index == len(self.cities): raise StopIteration city = self.cities[self.index] self.index += 1 return self.get_weather(city) def get_weather(self, city): url = 'http://wthrcdn.etouch.cn/weather_mini?city=' + city r = requests.get(url) data = r.json()['data']['forecast'][0] return city, data['high'], data['low'] class WeatherIterable(Iterable): def __init__(self, cities): self.cities = cities def __iter__(self): return WeatherIterator(self.cities) def show(w): for x in w: print(x) w = WeatherIterable(['北京', '上海', '广州'] * 10) show(w)
参考资料:python3实用编程技巧进阶