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的绘图工具matplotlib使用实例
Jul 03 Python
跟老齐学Python之重回函数
Oct 10 Python
Python远程桌面协议RDPY安装使用介绍
Apr 15 Python
Python字符串逐字符或逐词反转方法
May 21 Python
Python在图片中添加文字的两种方法
Apr 29 Python
python处理xml文件的方法小结
May 02 Python
python实现决策树C4.5算法详解(在ID3基础上改进)
May 31 Python
教你学会使用Python正则表达式
Sep 07 Python
Python DataFrame 设置输出不显示index(索引)值的方法
Jun 07 Python
使用Python更换外网IP的方法
Jul 09 Python
Windows系统Python直接调用C++ DLL的方法
Aug 01 Python
matplotlib阶梯图的实现(step())
Mar 02 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读取excel文件的简单实例
2013/08/26 PHP
is_uploaded_file函数引发的不能上传文件问题
2013/10/29 PHP
PHP的Yii框架中行为的定义与绑定方法讲解
2016/03/18 PHP
PHP isset empty函数相关面试题及解析
2020/12/11 PHP
比较不错的JS/JQuery显示或隐藏文本的方法
2014/02/13 Javascript
JavaScript中的正则表达式简明总结
2014/04/04 Javascript
javascript作用域链(Scope Chain)用法实例解析
2015/11/30 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
javascript点击按钮实现隐藏显示切换效果
2016/02/03 Javascript
jquery.validate[.unobtrusive]和Bootstrap实现tooltip错误提示问题分析
2016/10/30 Javascript
使用Curl命令查看请求响应时间方法
2016/11/04 Javascript
jquery实现下拉菜单的手风琴效果
2017/07/23 jQuery
iframe高度自适应及隐藏滚动条的实例详解
2017/09/29 Javascript
ajax与jsonp的区别及用法
2018/10/16 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧滑动,右侧不动)
2019/01/23 Javascript
js实现经典贪吃蛇小游戏
2020/03/19 Javascript
[49:08]Secret vs VP 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Mac OS X10.9安装的Python2.7升级Python3.3步骤详解
2013/12/04 Python
python列表去重的二种方法
2014/02/14 Python
python求众数问题实例
2014/09/26 Python
Python脚本实现DNSPod DNS动态解析域名
2015/02/14 Python
Python中强大的命令行库click入门教程
2016/12/26 Python
Python 25行代码实现的RSA算法详解
2018/04/10 Python
pandas使用apply多列生成一列数据的实例
2018/11/28 Python
彻底理解Python中的yield关键字
2019/04/01 Python
HTML5标签大全
2016/11/23 HTML / CSS
canvas进阶之贝塞尔公式推导与物体跟随复杂曲线的轨迹运动
2018/01/10 HTML / CSS
经济实惠的豪华背包和行李袋:Packs Project
2018/10/17 全球购物
Farfetch阿联酋:奢侈品牌时尚购物平台
2019/07/26 全球购物
考试违纪检讨书
2014/02/02 职场文书
园林专业毕业生自荐信
2014/07/04 职场文书
无财产离婚协议书范本
2014/10/28 职场文书
2015年全国“爱牙日”宣传活动总结
2015/03/23 职场文书
浅谈redis五大数据结构和使用场景
2021/04/12 Redis
MySQL数据库查询进阶之多表查询详解
2022/04/08 MySQL
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python