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 相关文章推荐
利用aardio给python编写图形界面
Aug 21 Python
Python深度优先算法生成迷宫
Jan 22 Python
Numpy中矩阵matrix读取一列的方法及数组和矩阵的相互转换实例
Jul 02 Python
对Python 获取类的成员变量及临时变量的方法详解
Jan 22 Python
利用python实现在微信群刷屏的方法
Feb 21 Python
用sqlalchemy构建Django连接池的实例
Aug 29 Python
Python openpyxl模块原理及用法解析
Jan 19 Python
Python安装whl文件过程图解
Feb 18 Python
python 将列表里的字典元素合并为一个字典实例
Sep 01 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
Nov 27 Python
pytorch中的model.eval()和BN层的使用
May 22 Python
LeetCode189轮转数组python示例
Aug 05 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的sprintf函数的用法 控制浮点数格式
2014/02/14 PHP
PHP实现多关键字加亮功能
2016/10/21 PHP
php设计模式之享元模式分析【星际争霸游戏案例】
2020/03/23 PHP
JavaScript中的其他对象
2008/01/16 Javascript
用JavaScript实现UrlEncode和UrlDecode的脚本代码
2008/07/23 Javascript
Node.js编码规范
2014/07/14 Javascript
JavaScript中获取样式的原生方法小结
2014/10/08 Javascript
jQuery ajax提交Form表单实例(附demo源码)
2016/04/06 Javascript
SpringMVC简单整合Angular2的示例
2017/07/31 Javascript
Vue实现web分页组件详解
2017/11/28 Javascript
在Vue中使用echarts的方法
2018/02/05 Javascript
python对html代码进行escape编码的方法
2015/05/04 Python
Python中的zipfile模块使用详解
2015/06/25 Python
python中将函数赋值给变量时需要注意的一些问题
2017/08/18 Python
深入学习Python中的上下文管理器与else块
2017/08/27 Python
python绘制简单折线图代码示例
2017/12/19 Python
Python简单计算给定某一年的某一天是星期几示例
2018/06/27 Python
为什么str(float)在Python 3中比Python 2返回更多的数字
2018/10/16 Python
Python数据结构之栈、队列及二叉树定义与用法浅析
2018/12/27 Python
python给微信好友定时推送消息的示例
2019/02/20 Python
使用python进行广告点击率的预测的实现
2019/07/04 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
Django用户认证系统 Web请求中的认证解析
2019/08/02 Python
在python里使用await关键字来等另外一个协程的实例
2020/05/04 Python
Internal修饰符有什么含义
2013/07/10 面试题
什么是继承
2013/12/07 面试题
工程业务员工作职责
2013/12/07 职场文书
关于圣诞节的广播稿
2014/01/26 职场文书
煤矿安全生产标语
2014/06/06 职场文书
信息管理与信息系统专业求职信
2014/06/21 职场文书
党的生日演讲稿
2014/09/10 职场文书
审计局2014法制宣传日活动总结
2014/11/01 职场文书
2015年高考寄语或鼓励的话
2015/03/23 职场文书
村党总支部公开承诺书2016
2016/03/25 职场文书
MySQL空间数据存储及函数
2021/09/25 MySQL
Python 读取千万级数据自动写入 MySQL 数据库
2022/06/28 Python