从一个实际小例子来看python中迭代器的应用

需求:
某软件要求,从网络抓取各个城市的气温信息,并依次显示:
北京: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)
原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13263693.html