实现可迭代对象与迭代器对象

在写爬虫的时候我们需要将爬取出来的内容先封装到一个对象中,然后再用for语句循环迭代出来数据,而不是将抓取出来的数据一次性的显示,因为这样既浪费存储空间而且由于网络IO处理起来还慢,这时候就需要用到迭代器了。

from collections import Iterable, Iterator
import requests


class WeatherIterator(Iterator):
    def __init__(self, caties):
        self.caties = caties
        self.index = 0

    def __next__(self):
        if self.index == len(self.caties):
            raise StopIteration
        city = self.caties[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)

使用生成器函数实现可迭代对象

一个模拟案例:实现一个可迭代对象的类,使它能迭代出给定范围内所有的质数。

from collections import Iterable

class PrimeNumbers(Iterable):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __iter__(self):
        for k in range(self.a, self.b + 1):
            if self.is_prime(k):
                yield k

    def is_prime(self, k):
        return False if k < 2 else all(map(lambda x: k % x, range(2, k)))

pn = PrimeNumbers(1, 30)
for n in pn:
    print(n)

自己实现反向迭代

功能类似于将range步进值设置为正数时为正向迭代,设置为负数时为反向迭代。

from decimal import Decimal

class FloatRange:
    def __init__(self, a, b, step):
        self.a = Decimal(str(a))
        self.b = Decimal(str(b))
        self.step = Decimal(str(step))

    def __iter__(self):
        t = self.a
        while t <= self.b:
            yield float(t)
            t += self.step

    def __reversed__(self):
        t = self.b
        while t >= self.a:
            yield float(t)
            t -= self.step

fr = FloatRange(3.0, 4.0, 0.2)
for x in fr:
    print(x)

print('-' * 20)

for x in reversed(fr):
    print(x)

"""
4.0
--------------------
4.0
3.8
3.6
3.4
3.2
3.0
"""