一. 如何进行反向迭代以及如何实现反向迭代
实际案例:
- 实现一个连续浮点数发生器FloatRange(和xrange类似),根据给定范围(start,end)和步进值(step)产生一系列连续的浮点数,如迭代FloatRange(3.0,4.0,0.2)可产生序列:
正向:3.0 -> 3.2 -> 3.4 -> 3.6 -> 3.8 -> 4.0
反向:4.0 -> 3.8 -> 3.6 ->3.4 ->3.2 ->3.0
解决方案:
实现反向迭代协议的__reversed__方法,他返回一个反向迭代器
代码示例:
# _*_ coding:utf-8 _*_
# @Author : TianYu
# @Time : 2017/10/11 14:52
# @File : 如何进行反向迭代以及如何实现.py
#序列的反向迭代
L = [1,2,3,4]
# L.reverse()#利用reverse反序,再进行迭代(会改变原列表,有些情况下不允许)
# l = L[::-1]#利用切片操作(会产生与原列表等大的新列表,某种程度上来说也是不允许的,浪费)
for x in reversed(L):#推荐使用,其实是调用__reversed__方法
print(x)
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
for x in FloatRange(1.0,4.0,0.5):#正向迭代
print(x)
for x in reversed(FloatRange(1.0,4.0,0.5)):#反向迭代
print(x)
二. 如何对迭代器进行切片操作
实际案例:
- 有某个文本文件,我们想读取其中某范围的内容,如100 - 300行之间的内容,Python中文本文件是可迭代对象,我们是否可以使用类似列表切片的方式得到一个100 - 300行文件内容的生成器?
f = open('/var/log/dmesg') #Linux 系统下的文件
f[100 : 300] #可以吗?
解决方案:
1.使用标准库中itertools.islice,它能返回一个迭代对象切片的生成器
代码示例:
# _*_ coding:utf-8 _*_
# @Author : TianYu
# @Time : 2017/10/11 15:09
# @File : 如何对迭代器进行切片操作.py
#方法1 使用readlines()方法(一次性的把整个文件的内容全部读入到列表中,
# 如果文件很大的话,可能会造成内存不足)
#所以不推荐使用
f = open('history')
line = f.readlines()#将文件的每一行读入到列表中
line = line[100:300]#之后对列表进行切片操作
#最好方法:使用迭代协议
f.seek(0)#文件指针返回到头部
for line in f:
print(line)
#问题解决方法
from itertools import islice
for line in islice(f,100,300):#islice不支持负索引,但可以为None
print(line)
三. 如何在一个 for 语句中迭代多个可迭代对象?
实际案例:
- 某班学生期末考试成绩,语文,数学,英语分别存储在3个列表中,同时迭代三个列表,计算每个学生的总分。(并行)
- 某年级有4个班级,某次考试每班英语成绩分别存储在4个列表中,依次迭代每个列表,统计全学年成绩高于90分的人数。(串行)
解决方案:
- (并行)使用内置函数zip,它能将多个可迭代对象合并,每次迭代返回一个元组
2.(串行)使用标准库中的itertools,chain,它能将多个可迭代对象连接
代码示例:
# _*_ coding:utf-8 _*_
# @Author : TianYu
# @Time : 2017/10/12 15:33
# @File : 迭代多个可迭代对象.py
from random import randint
#利用random模块创建学科成绩并保存在列表中
chinese = [randint(60,100) for _ in range(40)]
math = [randint(60,100) for _ in range(40)]
english = [randint(60,100) for _ in range(40)]
for i in range(len(math)):
print(chinese[i] + math[i] + english[i])#不推荐,不是所有的可迭代对象都支持索引操作,比如生成器
#zip方法
s = zip([1,2,3,4],('a', 'b','c', 'd')) #元素长度不一致时 取短
s1 = zip([1,2,3,4],('a', 'b','c', 'd'),[7, 8, 9, 10])
print(list(s)) #[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
print(list(s1)) #[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), [7, 8, 9, 10]]
#方法 2 并行情况
total = []
for c, m, e in zip(chinese, math, english):
total.append(c + m + e)
print(total)
#方法 3 串行情况
#itertools.chain 能将多个可迭代对象连接
from itertools import chain
#chain(*iterables) --> chain object 传入多个可迭代对象
for x in chain([1,2,3,4],['a','b','c','d']):
print(x) # 1 2 3 4 a b c d
e1 = [randint(60,100) for _ in range(40)] #生成四个班的英语成绩
e2 = [randint(60,100) for _ in range(42)]
e3 = [randint(60,100) for _ in range(42)]
e4 = [randint(60,100) for _ in range(39)]
count = 0
for s in chain(e1, e2, e3, e4):
if s > 90:
count += 1
print(count)