这里有新鲜出炉的 Python3 官方中文指南,程序狗速度看过来!
Python 是一种面向对象、解释型计算机程序设计语言,由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。Python 语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够把用其他语言制作的各种模块(尤其是 C/C++)很轻松地联结在一起。
这篇文章主要介绍了 Python 迭代器与生成器实例详解的相关资料, 需要的朋友可以参考下
Python 迭代器与生成器实例详解
一、如何实现可迭代对象和迭代器对象
1. 由可迭代对象得到迭代器对象
例如 l 就是可迭代对象,iter(l) 是迭代器对象
- In [1]: l = [1,2,3,4]
- In [2]: l.__iter__
- Out[2]: <method-wrapper '__iter__' of list object at 0x000000000426C7C8>
- In [3]: t = iter(l)
- In [4]: t.next()
- Out[4]: 1
- In [5]: t.next()
- Out[5]: 2
- In [6]: t.next()
- Out[6]: 3
- In [7]: t.next()
- Out[7]: 4
- In [8]: t.next()
- ---------------------------------------------------------------------------
- StopIteration Traceback (most recent call last)
- <ipython-input-8-3660e2a3d509> in <module>()
- ----> 1 t.next()
- StopIteration:
- for x in l:
- print x
- for 循环的工作流程,就是先有iter(l)得到一个t,然后不停的调用t.nex(),到最后捕获到StopIteration,就结束迭代
# 下面这种直接调用函数的方法如果数据量大的时候会对网络 IO 要求比较高,可以采用迭代器的方法
- def getWeather(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'])
- print getWeather(u'北京')
- 返回值:北京:低温 13℃,高温 28℃
实现一个迭代器对象 WeatherIterator,next 方法每次返回一个城市气温
实现一个可迭代对象 WeatherIterable,iter 方法返回一个迭代器对象
- # -*- coding:utf-8 -*-
- 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'])
- 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'深圳']):
- print x.encode('utf-8')
- 输出:
- 北京:低温 13℃,高温 28℃
- 上海:低温 14℃,高温 22℃
- 广州:低温 17℃,高温 23℃
- 深圳:低温 18℃,高温 24℃
二、使用生成器函数实现可迭代对象
1. 实现一个可迭代对象的类,它能迭代出给定范围内所有素数
素数定义为在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的数称为素数。
一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
- 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 xrange(2, k):
- if k % i == 0:
- return False
- return True
- def __iter__(self):
- for k in xrange(self.start, self.end + 1):
- if self.isPrimeNum(k):
- yield k
- for x in PrimeNumbers(1, 10):
- print x
- 输出:
- 2
- 3
- 5
- 7
三、实现反向迭代
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
- 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 round(t,14) <= round(self.end, 14):
- yield t
- t = t + self.step
- def __reversed__(self):
- t = self.end
- while round(t, 14) >= round(self.start, 14):
- yield t
- t = t - self.step
- for x in reversed(FloatRange(3.0, 4.0, 0.2)):
- print x
- 输出:
- 4.0
- 3.8
- 3.6
- 3.4
- 3.2
- 3.0
- for x in FloatRange(3.0, 4.0, 0.2):print x输出:3.03.23.43.63.84.0
上面代码采用 round 函数是因为浮点数比较会有精度问题,所以需要进行四舍五入
2. 对迭代器进行切片操作
例如: 有某个文本文件,想读取其中某范围的内容,如 100-300 行之间的内容,python 中文本文件是可迭代对象,是否可以使用类似列表切片的方式得到一个 100-300 行文件内容的生成器
使用标准库中的 itertools.islice, 它能返回一个迭代对象切片的生成器
- f = open('/var/log/dmesg')
- from itertools import islice
- # 对文件内容100到300行之间进行切片,返回的是个生成器对象,默认歩径是1
- islice(f, 100, 300)
- # 前500行内容
- islice(f, 500)
- # 100行到末尾结束内容
- islice(f, 100, None)
- ps: 每次使用islice要重新申请对象,它会消耗原来的迭代对象
四、 迭代多个对象
1. 在一个 for 语句中迭代多个可迭代对象
1、某班学生考试成绩语文、数学、英语分别存储在 3 个列表中,同时迭代三个列表,计算三个学生的总分(并行)
2、某年级四个班,某次考试每班英语成绩分别存储在 4 个列表中,依次迭代每个列表,统计全学年英语成绩高于 90 分人数(串行)
解决方案:
并行: 使用内置函数 zip,它能将多个可迭代对象合并,每次迭代返回一个元组
- from random import randint
- chinese = [randint(60,100) for _ in xrange(40)]
- math = [randint(60,100) for _ in xrange(40)]
- english = [randint(60,100) for _ in xrange(40)]
- total = []
- for c,m,e in zip(chinese, math,english):
- total.append(c+m+e)
- print total
- 输出:
- [204, 227, 238, 201, 227, 205, 251, 274, 210, 242, 220, 239, 237, 207, 230, 267, 263, 240, 247, 249, 255, 268, 209, 270, 259, 251, 245, 262, 234, 221, 236, 250, 251, 249, 242, 255, 232, 272, 237, 253]
串行: 使用标准库中的 itertools.chain, 它能将多个可迭代对象连接
- from random import randint
- from itertools import chain
- class1 = [randint(60,100) for _ in xrange(40)]
- class2 = [randint(60,100) for _ in xrange(42)]
- class3 = [randint(60,100) for _ in xrange(39)]
- class4 = [randint(60,100) for _ in xrange(43)]
- count = 0
- for s in chain(class1, class2, class3, class4):
- if s > 90:
- count = count + 1
- print count
- 输出:
- 38
来源: http://www.phperz.com/article/17/0622/335402.html