实际案例:
某软件要求,从网络抓取各个城市气温信息,并依次显示:
北京:15~20
天津:17~22
长春:12~18
... ...
如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延时,并且浪费存储空间。我们期望以"用时访问"的策略,并且能把所有城市气温封装到一个对象里,可用for语句进行迭代。如何解决?
解决方案:
Step1:实现一个迭代器对象WeatherIterator,用__next__(方法每次返回一个城市气温。
Step2:实现一个可迭代对象WeatherIterable,用__iter__()方法返回一个迭代器对象。
2、代码演示(1)获取一个城市气温的函数实现
# _*_ encoding:utf-8 _*_
import requests
def get_weather(city):
# 获取一个城市的气温函数
r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city=' + city)
print(r.json())
data = r.json()['data']['forecast'][0]
return '%s: %s, %s' % (city, data['low'], data['high'])
# [u'北京', u'上海', u'广州', u'长春']
print(get_weather(u'北京'))
print(get_weather(u'长春'))
(2)查看迭代器对象和迭代对象的抽象接口
from collections.abc import Iterable, Iterator
# 查看迭代器的抽象接口,frozenset({'__next__'})
print(dir(Iterator))
print(Iterator.__abstractmethods__)
# 查看迭代对象的抽象接口,frozenset({'__iter__'})
print(dir(Iterable))
print(Iterable.__abstractmethods__)
(3)实现天气迭代器对象和迭代对象
注:继承迭代器或迭代对象时,必须实现包含抽象方法,如:(2)
# _*_ encoding:utf-8 _*_
from collections.abc import Iterable, Iterator
import requests
# 实现天气迭代器继承Iterator
class Weather_Iterator(Iterator):
def __init__(self, cities):
# 定义构造器
self.cities = cities # 城市列表
self.index = 0 # 迭代位置
def get_weather(self, city):
# 获取一个城市的气温函数
r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city=' + city)
data = r.json()['data']['forecast'][0]
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.get_weather(city)
# 实现天气的可迭代对象,继承Iterable
class Weather_Iterable(Iterable):
def __init__(self, cities):
self.cities = cities
def __iter__(self):
# 返回一个Weather_Iterator实例
return Weather_Iterator(self.cities)
# [u'北京', u'上海', u'广州', u'长春']
for x in Weather_Iterator([u'北京', u'上海', u'广州', u'长春']):
print(x)
# 运行结果:
北京: 低温 8℃, 高温 13℃
上海: 低温 15℃, 高温 22℃
广州: 低温 24℃, 高温 31℃
长春: 低温 3℃, 高温 14℃



