zoukankan      html  css  js  c++  java
  • 迭代器和可迭代对象

    下面大段内容转自:知乎 作者灵剑
    这是个和多态有关的问题,Python中关于迭代有两个概念,第一个是Iterable,第二个是Iterator,协议规定Iterable的__iter__方法会返回一个Iterator, Iterator的__next__方法(Python 2里是next)会返回下一个迭代对象,如果迭代结束则抛出StopIteration异常。
    同时,Iterator自己也是一种Iterable,所以也需要实现Iterable的接口,也就是__iter__,这样在for当中两者都可以使用。Iterator的__iter__只需要返回自己就行了。这样,下面的代码就可以工作:
    for i in my_list:
        ...
    
    for i in iter(mylist):
        ...
    
    for i in (v for v in mylist if v is not None):
        ...
    

    Python中许多方法直接返回iterator,比如itertools里面的izip等方法,如果Iterator自己不是Iterable的话,就很不方便,需要先返回一个Iterable对象,再让Iterable返回Iterator。生成器表达式也是一个iterator,显然对于生成器表达式直接使用for是非常重要的。
    那么为什么不只保留Iterator的接口而还需要设计Iterable呢?许多对象比如list、dict,是可以重复遍历的,甚至可以同时并发地进行遍历,通过__iter__每次返回一个独立的迭代器,就可以保证不同的迭代过程不会互相影响。而生成器表达式之类的结果往往是一次性的,不可以重复遍历,所以直接返回一个Iterator就好。让Iterator也实现Iterable的兼容就可以很灵活地选择返回哪一种。

    总结来说Iterator实现的__iter__是为了兼容Iterable的接口,从而让Iterator成为Iterable的一种实现。

    for循环为了兼容性其实有两种机制,如果对象有__iter__会使用迭代器,但是如果对象没有__iter__,但是实现了__getitem__,会改用下标迭代的方式。我们可以试一下:
    >>> class NotIterable(object):
    ...     def __init__(self, baselist):
    ...         self._baselist = baselist
    ...     def __getitem__(self, index):
    ...         return self._baselist[index]
    ...
    >>> t = NotIterable([1,2,3])
    >>> for i in t:
    ...     print i
    ...
    1
    2
    3
    >>> iter(t)
    <iterator object at 0x0345E3D0>
    

     

    当for发现没有__iter__但是有__getitem__的时候,会从0开始依次读取相应的下标,直到发生IndexError为止,这是一种旧的迭代协议。iter方法也会处理这种情况,在不存在__iter__的时候,返回一个下标迭代的iterator对象来代替。一个重要的例子是str,字符串就是没有__iter__接口的。
     
    自定义可迭代对象和迭代器:
    from collections import Iterator,Iterable
    import requests,json
    
    class WeatherItertor(Iterator):
        def __init__(self,city_list):
            self.CityList = city_list
            self.indexA = 0
    
        def getWeather(self,city):
            r = requests.get('http://www.weather.com.cn/data/sk/{code}.html'.format(code=city))
            ret = json.loads(r.content.decode("utf-8"))
            #风向
            WD = ret["weatherinfo"]["WD"]
            #城市
            city_data = ret["weatherinfo"]["city"]
            return "城市:{city},风向:{WD}".format(city=city_data,WD=WD)
    
        def __next__(self):
            if self.indexA == len(self.CityList):
                raise StopIteration
            city = self.CityList[self.indexA]
            self.indexA += 1
            return  self.getWeather(city)
    
    
    class WeatherIterable(Iterable):
        def __init__(self,city_list):
            self.CityList =city_list
    
        def __iter__(self):
            return WeatherItertor(self.CityList)
    
    
    
    # citys = {'北京':101010100,'朝阳':101010300,'顺义':101010400,'怀柔':101010500}
    citys_list = [101010100,101010300,101010400,101010500]
    for x in  WeatherIterable(citys_list):
        print(x)
    

      

  • 相关阅读:
    类似直播点赞动画(出现一颗心缓缓升起然后消失)
    进入App弹出提示框
    iOS NSString 截取字符串(根据索引截取)
    刷新tableView 保持头部视图 不变
    截取一段字符串中,两个指定字符串中间的字符串
    ios 导航栏透明, 上下滑动 导航栏 颜色渐变
    ios 自定义键盘的return键以及键盘的其他一些属性
    百度地图通过坐标定位 自己的位置显示小圆点 (精度圈是否显示根据自己喜好) 上图
    百度地图定位 (直接上图上代码)
    iOS 对H5加载html的数据的一些基础设置
  • 原文地址:https://www.cnblogs.com/BGPYC/p/7502180.html
Copyright © 2011-2022 走看看