zoukankan      html  css  js  c++  java
  • Python对象迭代与反迭代相关问题与解决技巧

     

    1.如何实现可迭代对象和迭代器对象(1)

    In [1]:
    # 列表和字符串都是可迭代对象
    
    l = [1,2,3,4]
    
    In [2]:
    s = 'abcde'
    
    In [3]:
    for x in l:print(x)
    
     
    1
    2
    3
    4
    
    In [4]:
    for x in s:print(x)
    
     
    a
    b
    c
    d
    e
    
    In [5]:
    iter(l)
    
    Out[5]:
    <list_iterator at 0x7fde5571c208>
    In [6]:
    iter(s)
    
    Out[6]:
    <str_iterator at 0x7fde5571c710>
    In [7]:
    l.__iter__()
    
    Out[7]:
    <list_iterator at 0x7fde5571ca90>
    In [8]:
    # 迭代器对象
    
    t = iter(l)
    
    In [9]:
    next(t)
    
    Out[9]:
    1
    In [10]:
    next(t)
    
    Out[10]:
    2
    In [11]:
    next(t)
    
    Out[11]:
    3
    In [12]:
    t2 = iter(s)
    
    In [13]:
    next(t2)
    
    Out[13]:
    'a'
    In [14]:
    next(t2)
    
    Out[14]:
    'b'
     

    2.如何实现可迭代对象和迭代器对象(2)

     

    ''' 从网络抓取各个城市气温,并依次显示: 北京:12-16 上海:20-30 ... 如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延时,并且浪费存储空间,我们期望以'用时访问的策略', 并且能把所有城市气温封装到一个对象里,可用for语句进行迭代,如何解决? '''

    In [15]:
    import requests
    
    def getWeather(city):
        '''获取一个城市气温'''
        r = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=' + city)
        data = r.json()['data']['forecast'][0]
        
        return '%s:%s,%s' %(city,data['low'],data['high'])
    
    In [16]:
    getWeather('北京')
    
    Out[16]:
    '北京:低温 -7℃,高温 0℃'
    In [17]:
    getWeather('上海')
    
    Out[17]:
    '上海:低温 8℃,高温 10℃'
    In [18]:
    from collections import Iterable,Iterator
    
    In [19]:
    # 可迭代对象抽象接口
    Iterable.__abstractmethods__
    
    Out[19]:
    frozenset({'__iter__'})
    In [20]:
    # 迭代器对象抽象接口
    Iterator.__abstractmethods__
    
    Out[20]:
    frozenset({'__next__'})
    In [21]:
    import requests
    from collections import Iterable,Iterator
    
    class WeatherIterator(Iterator):
        '''实现一个迭代器对象WeatherIterator'''
        def __init__(self,cities):
            self.cities = cities
            #记录迭代位置
            self.index = 0
        
        def getWeather(self,city):
            '''获取单个城市气温数据'''
            r = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=' + city)
            data = r.json()['data']['forecast'][0]
            return '%s:%s,%s' %(city,data['low'],data['high'])
            
        def __next__(self):
            '''__next__方法每次返回一个城市气温'''
            if self.index == len(self.cities):
                raise StopIteration
            city = self.cities[self.index]
            self.index += 1
            return self.getWeather(city)
        
    class WeatherIterable(Iterable):
        '''实现一个可迭代对象WeatherIterable'''
        def __init__(self,cities):
            self.cities = cities
            
        def __iter__(self):
            '''__iter__方法返回一个迭代器对象'''
            return WeatherIterator(self.cities)
    
    In [22]:
    for city in WeatherIterable(['北京','上海','广州','深圳']):
        print(city)
    
     
    北京:低温 -7℃,高温 0℃
    上海:低温 8℃,高温 10℃
    广州:低温 9℃,高温 13℃
    深圳:低温 12℃,高温 15℃
    
     

    3.如何使用生成器函数实现可迭代对象

     

    ''' 实际案例: 实现一个可迭代对象的类,它能迭代出给定范围内的所有素数: pn = PrimeNumber(1, 30) for k in pn: print k

    输出结构: 2 3 5 7 11 13 17 19 23 29

    解决方案: 将该类的iter方法实现成生成器函数,每次yield返回一个素数 '''

    In [23]:
    def f():
        print('in f(),1')
        yield 1
        
        print('in f(),2')
        yield 2
        
        print('in f(),3')
        yield 3
        
    g = f()
    
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    
     
    in f(),1
    1
    in f(),2
    2
    in f(),3
    3
    
    In [24]:
    '''生成器对象即实现了可迭代对象接口,又实现了迭代器接口'''
    
    g = f()
    for x in g:
        print(x)
    
     
    in f(),1
    1
    in f(),2
    2
    in f(),3
    3
    
    In [25]:
    g.__iter__() is g
    
    Out[25]:
    True
    In [26]:
    # 使用生成器返回所有素数
    
    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
    
    In [27]:
    for x in PrimeNumbers(1,100):
        print(x)
    
     
    2
    3
    5
    7
    11
    13
    17
    19
    23
    29
    31
    37
    41
    43
    47
    53
    59
    61
    67
    71
    73
    79
    83
    89
    97
    
     

    4.如何进行反向迭代以及如何实现反向迭代

     

    ''' 实际案例: 实现一个连续浮点数发生器FloatRange(和xrange类似), 根据给定范围(start, end)和步进值(step)产生一系列连续浮点数, 如迭代FloatRange(3.0, 4.0, 0.2)可产生序列 '''

    In [28]:
    l = [1,2,3,4,5]
    
    In [29]:
    l.reverse()# 会改变原列表
    
    In [30]:
    # 切片操作,返回新的列表,但是浪费资源
    l1 = l[::-1]
    
    In [31]:
    # 列表的反向迭代器,与iter()对应
    reversed(l)
    
    Out[31]:
    <list_reverseiterator at 0x7fde55721358>
    In [32]:
    for x in reversed(l):
        print(x)
    
     
    1
    2
    3
    4
    5
    
    In [33]:
    # 实现正向和反向连续浮点序列
    class FloatRange:
        def __init__(self,start,end,step=0.1):
            self.start = start
            self.end = end
            self.step = step
            
        #正向迭代器
        def __iter__(self):
            t = self.start
            while t<= self.end:
                yield t
                t += self.step
                
        #反向迭代器   
        def __reversed__(self):
            t = self.end
            while t >= self.start:
                yield t
                t -= self.step
    
    In [34]:
    for x in FloatRange(1.0,4.0,0.5):
        print(x)
    
     
    1.0
    1.5
    2.0
    2.5
    3.0
    3.5
    4.0
    
    In [35]:
    for x in reversed(FloatRange(1.0,4.0,0.5)):
        print(x)
    
     
    4.0
    3.5
    3.0
    2.5
    2.0
    1.5
    1.0
    
     

    5.如何对迭代器做切片操作

    In [36]:
    f = open('Alice.txt')
    
    In [37]:
    ls_lines = f.readlines()
    # 会把文件指针移动到了文件最后
    cut_lines = ls_lines[1:5]
    print(cut_lines)
    # readlines会把整个文件导入到内存当中,文件过大时会出现内存不足
    
     
    ['she hadpeeped into the book her sister was reading, but it had nopictures or conversations in it, `and what is the use \n', "of a book,'thought Alice `without pictures or conversation?'So she was considering in her own mind (as well as she \n", 'could,for the hot day made her feel very sleepy and stupid), whetherthe pleasure of making a daisy-chain would be worth \n', 'the troubleof getting up and picking the daisies, when suddenly a WhiteRabbit with pink eyes ran close by her.There was \n']
    
    In [38]:
    # islice能返回一个迭代对象切片的生成器
    from itertools import islice
    
    islice(f,100,300)
    
    Out[38]:
    <itertools.islice at 0x7fde54cdcf48>
    In [39]:
    f.seek(0)# 把文件指针移动到文件最前
    for line in islice(f,20,25):
        print(line)
    
     
    Alice to herself, `after such a fall as this, Ishall think nothing of tumbling down stairs!  How brave they'llall think 
    
    me at home!  Why, I wouldn't say anything about it,even if I fell off the top of the house!' (Which was very 
    
    likelytrue.)Down, down, down.  Would the fall NEVER come to an end!  `Iwonder how many miles I've fallen by this time?' 
    
    she said aloud.`I must be getting somewhere near the centre of the earth.  Letme see:  that would be four thousand 
    
    miles down, I think--' (for,you see, Alice had learnt several things of this sort in herlessons in the schoolroom, and 
    
    
    In [40]:
    islice(f,30)#前30行
    islice(f,50,None)#50-最后一行
    
    Out[40]:
    <itertools.islice at 0x7fde54cca598>
    In [41]:
    l = range(20)
    
    In [42]:
    #生成l的迭代器
    t = iter(l)
    
    In [43]:
    #每次使用islice时,要重新申请一个可迭代对象,它会消耗这个迭代对象的资源
    for x in islice(t,5,10):
        print(x)
    
     
    5
    6
    7
    8
    9
    
    In [44]:
    #t已经迭代到位置10
    for x in t:
        print(x)
    
     
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
     

    6.如何在一个for语句中迭代多个可迭代对象

     

    ''' 实际案例: 1.某班学生期末成绩,语文,数学,英语分别存储在3个列表中, 同时迭代三个列表,计算每个学生的总分.(并行)

    解决方案: 并行: 使用内置函数zip,它能将多个可迭代对象合并,每次迭代返回一个元组. '''

    In [45]:
    from random import randint
    
    chinese = [randint(60,100) for _ in range(40)]
    math = [randint(60,100) for _ in range(40)]
    english = [randint(60,100) for _ in range(40)]
    
    In [46]:
    # 使用索引
    # 局限:如果不是列表,而是生成器的话,将不能用索引访问
    t = []
    for i in range(len(chinese)):
        t.append(chinese[i] + math[i] + english[i])
        
    print(t)
    
     
    [211, 198, 246, 238, 237, 244, 263, 217, 242, 226, 266, 238, 272, 249, 249, 222, 221, 265, 249, 234, 216, 213, 245, 236, 243, 239, 253, 244, 239, 264, 226, 231, 246, 255, 245, 236, 221, 229, 249, 217]
    
    In [47]:
    # 使用zip()函数
    total = []
    for c,m,e in zip(chinese,math,english):
        total.append(c + m + e)
        
    print(total)
    
     
    [211, 198, 246, 238, 237, 244, 263, 217, 242, 226, 266, 238, 272, 249, 249, 222, 221, 265, 249, 234, 216, 213, 245, 236, 243, 239, 253, 244, 239, 264, 226, 231, 246, 255, 245, 236, 221, 229, 249, 217]
    
     

    ''' 实际案例: 2.某年及有4个班,某次考试每班英语成绩分别存储在4个列表中, 依次迭代每个列表,统计全学年成绩高于90分人数.(串行)

    解决方案: 串行: 使用标准库中的itertools.chain,它能将多个可迭代对象连接. '''

    In [48]:
    from random import randint
    from itertools import chain
    
    
    c1 = [randint(60,100) for _ in range(40)]
    c2 = [randint(60,100) for _ in range(41)]
    c3 = [randint(60,100) for _ in range(42)]
    c4 = [randint(60,100) for _ in range(43)]
    
    count = 0
    
    for s in chain(c1,c2,c3,c4):
        if s > 90:
            count += 1
    
    In [49]:
    count
    
    Out[49]:
    37

  • 相关阅读:
    How to use Log4j 2 with Spring Boot
    SpringBoot使用Redis缓存
    win10下安装redis
    mysql 8.0.15修改密码
    spring-boot集成redis实现缓存功能
    Spring Boot(三):Spring Boot 中 Redis 的使用
    关于 iView-cdn模式
    HTML5 Audio-使用 Media 事件添加进度栏
    vue-cli中自定义路径别名 assets和static文件夹的区别
    CH9001: 各浏览器对常用或者错误的 Content-Type 类型处理方式不一致
  • 原文地址:https://www.cnblogs.com/prince5460/p/10097915.html
Copyright © 2011-2022 走看看