Python 迭代器与生成器实例详解


Posted in Python onMay 18, 2017

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.0
3.2
3.4
3.6
3.8
4.0

上面代码采用round函数是因为浮点数比较会有精度问题,所以需要进行四舍五入

2.对迭代器进行切片操作

例如: 有某个文本文件,想读取其中某范围的内容,如100-300行之间的内容,python中文本文件是可迭代对象,是否可以使用类似列表切片的方式得到一个100-300行文件内容的生成器

使用标准库中的itertools.islice,它能返回一个迭代对象切片的生成器

f = open('/var/log/dmesg')

from itertools import islice

# 对文件内容100到300行之间进行切片,返回的是个生成器对象,默认?i径是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

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Python 相关文章推荐
在Python中使用元类的教程
Apr 28 Python
Python3实战之爬虫抓取网易云音乐的热门评论
Oct 09 Python
python实现跨excel的工作表sheet之间的复制方法
May 03 Python
Python使用matplotlib模块绘制图像并设置标题与坐标轴等信息示例
May 04 Python
简单了解python的break、continue、pass
Jul 08 Python
PyQt Qt Designer工具的布局管理详解
Aug 07 Python
Python使用APScheduler实现定时任务过程解析
Sep 11 Python
浅谈Django QuerySet对象(模型.objects)的常用方法
Mar 28 Python
Keras中的两种模型:Sequential和Model用法
Jun 27 Python
python opencv pytesseract 验证码识别的实现
Aug 28 Python
python爬虫构建代理ip池抓取数据库的示例代码
Sep 22 Python
详解如何使用Pytest进行自动化测试
Jan 14 Python
Python字符串处理实例详解
May 18 #Python
Python进阶-函数默认参数(详解)
May 18 #Python
Python装饰器实现几类验证功能做法实例
May 18 #Python
如何用itertools解决无序排列组合的问题
May 18 #Python
详解使用python的logging模块在stdout输出的两种方法
May 17 #Python
Python中正则表达式详解
May 17 #Python
python算法演练_One Rule 算法(详解)
May 17 #Python
You might like
PHP利用APC模块实现大文件上传进度条的方法
2015/10/29 PHP
合格的PHP程序员必备技能
2015/11/13 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
PHP实现APP微信支付的实例讲解
2018/02/10 PHP
jquery解析JSON数据示例代码
2014/03/17 Javascript
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
2014/03/18 NodeJs
jQuery使用andSelf()来包含之前的选择集
2014/05/19 Javascript
JQuery实现展开关闭层的方法
2015/02/17 Javascript
jQuery使用hide方法隐藏元素自身用法实例
2015/03/30 Javascript
浅谈javascript中的constructor
2016/06/08 Javascript
浅谈js函数的多种定义方法与区别
2016/11/29 Javascript
Vue.js计算属性computed与watch(5)
2016/12/09 Javascript
JS 中使用Promise 实现红绿灯实例代码(demo)
2017/10/20 Javascript
Node.js实现mysql连接池使用事务自动回收连接的方法示例
2018/02/03 Javascript
JS实现json对象数组按对象属性排序操作示例
2018/05/18 Javascript
JavaScript模板引擎应用场景及实现原理详解
2018/12/14 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
2019/01/30 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
vue实现登录拦截
2020/06/29 Javascript
基于JavaScript实现大文件上传后端代码实例
2020/08/18 Javascript
Python合并字符串的3种方法
2015/05/21 Python
Python中import导入上一级目录模块及循环import问题的解决
2016/06/04 Python
Python爬虫实战:分析《战狼2》豆瓣影评
2018/03/26 Python
对python sklearn one-hot编码详解
2018/07/10 Python
python 反向输出字符串的方法
2018/07/16 Python
Python爬虫入门教程02之笔趣阁小说爬取
2021/01/24 Python
size?德国官方网站:英国伦敦的球鞋精品店
2018/03/17 全球购物
Ticketmaster意大利:音乐会、节日、艺术和剧院的官方门票
2019/12/23 全球购物
教师自我鉴定范文
2014/03/20 职场文书
俞敏洪励志演讲稿
2014/04/29 职场文书
小学教师工作总结2015
2015/04/07 职场文书
2015年采购员工作总结
2015/04/27 职场文书
联谊活动总结范文
2015/05/09 职场文书
2016毕业实习单位评语大全
2015/12/01 职场文书
MySQL的InnoDB存储引擎的数据页结构详解
2022/03/03 MySQL
日本十大血腥动漫,那些被禁播的动漫盘点
2022/03/21 日漫