可迭代对象和迭代器

可迭代对象和迭代器

1.首先可以用于for循环的对象统称为可迭代对象(Interable),像list dict str都是可迭代对象。可以被next()函数调用并不断返回下一个值的对象成为迭代器(Interable)。
看一下函数的实现:

class Iterable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __iter__(self):         ##使用__iter__是迭代对象变为迭代器
        while False:
            yield None

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Iterator(Iterable):

    __slots__ = ()

    @abstractmethod
    def __next__(self):
        'Return the next item from the iterator. When exhausted, raise StopIteration'
        raise StopIteration

    def __iter__(self):
        return self

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterator:
            if (any("__next__" in B.__dict__ for B in C.__mro__) and
                any("__iter__" in B.__dict__ for B in C.__mro__)):
                return True
        return NotImplemented

可以看到Iterable有一个__iter__函数,Iterator继承于Iterable。Iterator除了__iter__函数外,还有一个__next__函数,这样迭代器就可以使用next方法进行迭代,可迭代对象可以使用iter()将可迭代对象变为迭代器。迭代器的主要优点呢就是支持延迟计算,不需要你事先准备好整个需要迭代的数据,而在此之前元素可以不存在或者销毁,这种特性使它使用一个巨大的或者无线的集合,只要实现了__iter__就可以使用迭代器访问了可迭代对象,就可以使用iter()方法使可迭代对象变为迭代器而迭代器中的__next__会返回下一个迭代对象。因为迭代操作如此普遍,Python专门将关键字for用作了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。for为了兼容性其实有两种机制,如果对象有__iter__会使用迭代器,但是如果对象没有__iter__,但是实现了__getitem__,会改用下标迭代的方式。

2.实现一个迭代器和迭代对象

import requests
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)
        data = r.json()['data']['forecast'][0]
        return '%s: %s , %s' % (city,data['low'],data['high'])
    # next调用getWeather方法
    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)

for x in WeatherIterable([u'北京',u'上海',u'保定',u'湘潭']):
    # x就是getWeather return的结果
    print(x)

3.如何使用生成器函数实现可迭代对象:
首先生成器是一种特殊的迭代器,他里面已经有__next__,同时他也是一个迭代对象,里面也有__iter__,我们这里想实现一个可迭代对象来进行for循环,可以借助生成器来实现一个可迭代对象,否则还需要写一个迭代器(再实现一个__next__),这样我们想使用for循环迭代PrimeNumbers的时候,就可以直接在__iter__里面实现一个生成器,当for循环访问__iter__的时候,就可以让生成器帮我们完成迭代。

class PrimeNumbers:
    def __init__(self,start,end):
        self.start = start
        self.end = end
    def isPrimeNum(self,k):
        if k < 2:
            return False
        for i in range(2,k):
            if k % i == 0:
                return False
        return True
    def __iter__(self):   
        for k in range(self.start,self.end + 1):
            if self.isPrimeNum(k):
                yield k
n = 0
for x in PrimeNumbers(1,1235):

    print(x)
    n = n + 1
print(n)
posted @ 2018-01-05 23:38  BGPY  阅读(361)  评论(0编辑  收藏  举报