需求:
某软件要求,从网络抓取各个城市的气温信息,并依次显示:
北京:15-20
天津:17-22
长春:12-18
.....
如果一次抓取所有城市的天气再显示,显示第一个城市气温时,有很高的延时,并且浪费存储空间,我们期望以“用时访问”的策略,并且能把所有城市气温封装到一个对象中,可用for语句进行迭代,如何解决?
需求实现:
思路:
step1:实现一个迭代器对象weatherIterator,__next__方法每次返回一个城市气温
step2:实现一个可迭代对象weatherIterable,__iter__方法返回一个迭代器对象
代码:
import requests
# #[u'北京',u'上海',u'广州',u'长春']
# print(getweather(u'杭州'))
# print(getweather(u'南昌'))
from collections import Iterable,Iterator
class WeatherIterator(Iterator):
def __init__(self,cities):
self.cities = cities #要迭代的城市列表
self.index = 0 #初始的迭代位置,方便后续的取值
def getWeather(self,city):
r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city=' + city) #r:<Response [200]>
#print(r.json())
data = r.json()['data']['forecast'][0] #其中只有response返回为json格式时,用r.json()打印出响应的内容,
return '%s: %s , %s' % (city ,data['low'],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) #返回一个迭代器对象
if __name__=='__main__':
for x in WeatherIterable([u'北京',u'上海',u'广州',u'长春',u'南昌']): #这里用for循环来调用实际是调用可迭代对象的__iter__()方法,再调用迭代器对象的__next__()方法
print(x)
===========================================================================================
from collections import Iterable,Iterator
import requests
class WeatherIterator(Iterator):
def __init__(self,cities):
self.cities = cities
self.index = 0 # 通过index来确定具体迭代哪个城市的气温信息
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 = WeatherIterator(['北京','上海','广州'] * 10)
W = WeatherIterator(['北京','上海','广州'] * 10)
show(W)
print('-'*20) # 若是直接使用迭代器对象进行迭代,则下面的无结果,因为是迭代器对象是一次性的消费
show(W)
======================================================================================
# 通过生成器来实现,可以自动维护迭代状态,无需定义itreator的类
from collections import Iterable,Iterator
import requests
#class WeatherIterator(Iterator):
# def __init__(self,cities):
# self.cities = cities
# self.index = 0 # 通过index来确定具体迭代哪个城市的气温信息
#
#
# 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):
for city in self.cities:
yield 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']
def show(W):
for x in W:
print(x)
W = WeatherIterable(['北京','上海','广州'] * 10)
# W = WeatherIterator(['北京','上海','广州'] * 10)
show(W)
print('-'*20) # 若是直接使用迭代器对象进行迭代,则下面的无结果,因为是迭代器对象是一次性的消费
show(W)