可迭代对象和迭代器
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)