python高级编程技巧(4)

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

实际案例:

  1. 实现一个连续浮点数发生器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)

二. 如何对迭代器进行切片操作

实际案例:

  1. 有某个文本文件,我们想读取其中某范围的内容,如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 语句中迭代多个可迭代对象?

实际案例:

  1. 某班学生期末考试成绩,语文,数学,英语分别存储在3个列表中,同时迭代三个列表,计算每个学生的总分。(并行)
  2. 某年级有4个班级,某次考试每班英语成绩分别存储在4个列表中,依次迭代每个列表,统计全学年成绩高于90分的人数。(串行)
解决方案:
  1. (并行)使用内置函数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)

python高级编程技巧(4)_第1张图片
要努力要奋斗

你可能感兴趣的:(python高级编程技巧(4))