python进阶学习chapter03(迭代相关)

  • 如何实现可迭代对象和迭代器对象
  • 如何实现反向迭代
  • 如何实现在一个for循环中迭代多个可迭代对象
  • 对迭代器进行切片操作
  • itertools总结

一、如何实现可迭代对象和迭代器对象

重要概念!!!迭代器,可迭代对象,生成器,很容易绕晕了。

凡是可以使用for进行循环的就是可迭代对象,其中可以通过next方法逐步输出的就是迭代器,生成器的形成有两种:一种是把列表生成式改成(),一种是带有yield语句的。

具体的可以看:http://www.cnblogs.com/alex3714/articles/5765046.html

 

接下来进入主题:

 如何实现一个迭代器?

#实现一个迭代器
from collections import Iterator,Iterable
#构造迭代器
class WeatherIterator(Iterator):
    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)
        dict_data = r.json()['data']['forecast'][0]
        return "%s:%s,%s" % (city,dict_data['low'],dict_data['high'])

    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)
#生成迭代器对象
weatheriterator = WeatherIterator([u'北京',u'南京',u'上海'])
#迭代器对象调用next()方法
# print(weatheriterator.__next__())
# print(weatheriterator.__next__())
# print(weatheriterator.__next__())
for x in weatheriterator:
    print(x)

  Python 的迭代协议需要 _iter_() 方法返回一个实现了 _next_() 方法的迭代器对象。

二、如何实现反向迭代

参考:http://www.cnblogs.com/2bjiujiu/p/7248827.html

问题引入:

 实现一个连续的浮点数发生器,FloatRange,根据给定范围(start, end) 和步进值,产生一些列的浮点数,例如:FloatRange(3,4,0.2),将产生下列序列:

       正向:3.0 3.2 …… 4.0

       反向:4.0 3.8 …… 3.0

实现思路:

方法一、列表翻转(但是改变了原列表)

l = [1, 2, 3, 4, 5, 6]
l.reverse()
for i in l:
    print(i)

  方法二、列表切片(但是得到了和列表等大的列表,浪费空间)

l = [1, 2, 3, 4, 5, 6]
for i in l[::-1]:
    print(i)

  方法三、reversed()函数,返回一个反转的迭代器

l = [1, 2, 3, 4, 5, 6]
 
for i in reversed(l):
    print(i)

  for循环是调用的_iter_方法,反向迭代调用的是_reversed_方法

class FloatRange(object):
    def __init__(self, start, end, step):
        self.dot = self.__get_dot_num(step)
        # 有多少个小数点就乘以10的多少次幂,因为浮点数运算不准确,换算成整形数进行计算
        self.start = start*pow(10, self.dot)
        self.end = end*pow(10, self.dot)
        self.step = step*pow(10, self.dot)
         
    def __get_dot_num(self, step):
        # 计算step有多少个小数点
        if isinstance(step, int):
            return step
        else:
            # 通过round实现计算有多少位小数,首创
            for dot in range(len(str(step))+1):
                if step == round(step, dot):
                    return dot
 
    def __iter__(self):
        # 正向迭代
        while self.start <= self.end:
            yield self.start/pow(10, self.dot)
            self.start += self.step
 
    def __reversed__(self):
        # 反向迭代
        while self.end >= self.start:
            yield self.end/pow(10,self.dot)
            self.end -= self.step
 
if __name__ == '__main__':
     
    float_num_1 = FloatRange(2, 5, 0.1)
    float_num_2 = FloatRange(2, 5, 0.1)
     
    # 正向迭代
    for i in float_num_1:
        print(i)
         
    print('_'*60)
     
    # 反向迭代
    for x in reversed(float_num_2):
        print(x)

  

三、如何实现在一个for循环中迭代多个可迭代对象

问题引入:

1、如何同时迭代三个列表(并行):某班期末考试成绩分别存在语文、数学、英语三个列表中,计算每个学生的总分

2、如何依次迭代三个列表(串行):四个班级的英语成绩分别存在四个列表中,统计四个班高于90分的总人数

问题1、可以通过索引,也可以使用zip函数将三个列表打包成一个元组

from random import randint
 
 
def get_result(chinese, math, english):
    total = []
    # 循环索引进行取值,毕竟列表等长且成绩对应
    for index in range(len(chinese)):
        total.append(chinese[index] + math[index] + english[index])
    return total
或者:
def get_result(chinese, math, english):
    total = []
    # 通过zip函数进行迭代,实现同时迭代 3 个对象
    for c, m, e in zip(chinese, math, english):
        print(c, m, e)
        total.append(c + m + e)
    return total

 问题2、通过itertools中的chain

 

from random import randint
from itertools import chain
 
 
def get_result(e1, e2, e3):
    # 通过chain函数进行连续窜行迭代3个列表
    for i in chain(e1, e2, e3):
        print(i)

  

四、对迭代器进行切片操作

问题引入:如何读取某个文件的100~200行的内容呢

是否可以:

f=open()

f[100:200]

方法一、首先使用readlines()读取全部文件,然后再用切片操作,但是文件很大的时候就不适用

f = open()
f_all = f.readlines()
 
for i in f_all[100:200]:
       print(i)

 方法二、使用itertools的islice方法

f = open()
 
f_need = islice(f, 100, 200)
 
for i in f_need:
    print(i)

 五、itertools模块的总结

参见廖雪峰官网

 

posted @ 2018-06-18 21:42  水如如  阅读(130)  评论(0编辑  收藏  举报