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实现的解析crontab配置文件代码
Jun 30 Python
详解Python命令行解析工具Argparse
Apr 20 Python
EM算法的python实现的方法步骤
Jan 02 Python
Django中Model的使用方法教程
Mar 07 Python
Python 绘图库 Matplotlib 入门教程
Apr 19 Python
Python3内置模块之json编解码方法小结【推荐】
Dec 09 Python
PyQt5基本控件使用之消息弹出、用户输入、文件对话框的使用方法
Aug 06 Python
pandas 选取行和列数据的方法详解
Aug 08 Python
python脚本实现音频m4a格式转成MP3格式的实例代码
Oct 09 Python
python实现图像全景拼接
Mar 27 Python
解决pycharm 格式报错tabs和space不一致问题
Feb 26 Python
pytorch 如何使用float64训练
May 24 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 验证码实例代码
2010/06/01 PHP
PHP5.3连接Oracle客户端及PDO_OCI模块的安装方法
2016/05/13 PHP
PHP面向对象程序设计之对象生成方法详解
2016/12/02 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
JQuery浮动DIV提示信息并自动隐藏的代码
2010/08/29 Javascript
JavaScript根据数据生成百分比图和柱状图的实例代码
2013/07/14 Javascript
jqGrid 学习笔记整理——进阶篇(一 )
2016/04/17 Javascript
jQuery实现最简单实用的分秒倒计时
2017/02/05 Javascript
详解在Vue中通过自定义指令获取dom元素
2017/03/04 Javascript
JS实现将二维数组转为json格式字符串操作示例
2018/07/12 Javascript
create-react-app使用antd按需加载的样式无效问题的解决
2019/02/26 Javascript
微信小程序登录对接Django后端实现JWT方式验证登录详解
2019/07/29 Javascript
在Vue项目中使用Typescript的实现
2019/12/19 Javascript
Vue 封装防刷新考试倒计时组件的实现
2020/06/05 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
2020/09/22 Javascript
原生JavaScript实现弹幕组件的示例代码
2020/10/12 Javascript
[02:38]DOTA2超级联赛专访Loda 认为IG世界最强
2013/05/27 DOTA
[46:53]Secret vs Liquid 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python定时器使用示例分享
2014/02/16 Python
python使用rpc框架gRPC的方法
2018/08/24 Python
python 计算数据偏差和峰度的方法
2019/06/29 Python
Pycharm修改python路径过程图解
2020/05/22 Python
Bealls Florida百货商店:生活服饰、家居装饰和鞋子
2018/02/23 全球购物
报关专员求职信范文
2014/02/22 职场文书
文明市民先进事迹
2014/05/15 职场文书
预备党员转正考核材料
2014/06/03 职场文书
出生医学证明书
2014/09/15 职场文书
医院营销工作计划
2015/01/16 职场文书
委托公证书格式
2015/01/26 职场文书
男方婚前保证书
2015/02/28 职场文书
干货:如何写好工作计划!
2019/05/17 职场文书
《别在吃苦的年纪选择安逸》读后感3篇
2019/11/30 职场文书
使用nginx动态转换图片大小生成缩略图
2021/03/31 Servers
SQL Server数据定义——模式与基本表操作
2021/04/05 SQL Server
canvas多重阴影发光效果实现
2021/04/20 Javascript
原生Js 实现的简单无缝滚动轮播图的示例代码
2021/05/10 Javascript