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

    可迭代对象和迭代器

    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)
  • 相关阅读:
    MySQL数据表命令
    Linux 系统多台主机之间做SSH免密码登陆
    CentOS7配置NFS网络文件系统
    windows10下安装pygame并验证成功
    Docker中的Dockerfile命令详解FROM RUN COPY ADD ENTRYPOINT...
    Docker中使用多阶段Dockerfile构建容器镜像image(镜像优化)
    CentOS7Linux中Docker容器平台的使用
    linux下文件的压缩与解压缩
    Linux修改系统默认Bash shell为Zsh shell
    CentOSLinux系统中Ansible自动化运维的安装以及利用Ansible部署JDK和Hadoop
  • 原文地址:https://www.cnblogs.com/BGPYC/p/8207294.html
Copyright © 2011-2022 走看看