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缩进区别分析
Feb 15 Python
Python正则表达式教程之一:基础篇
Mar 02 Python
Django中的CBV和FBV示例介绍
Feb 25 Python
PyQt5每天必学之拖放事件
Aug 27 Python
pandas 两列时间相减换算为秒的方法
Apr 20 Python
pytorch permute维度转换方法
Dec 14 Python
pandas实现将dataframe满足某一条件的值选出
Jun 12 Python
tensorflow实现从.ckpt文件中读取任意变量
May 26 Python
Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)
Jul 07 Python
python解包用法详解
Feb 17 Python
Python机器学习之基于Pytorch实现猫狗分类
Jun 08 Python
Python实战之OpenCV实现猫脸检测
Jun 26 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以指定字段为索引返回数据库所取的数据数组
2013/06/30 PHP
php实现在线考试系统【附源码】
2018/09/18 PHP
Thinkphp集成抖音SDK的实现方法
2020/04/28 PHP
一步一步教你写一个jQuery的插件教程(Plugin)
2009/09/03 Javascript
jQuery 加上最后自己的验证
2009/11/04 Javascript
js实现class样式的修改、添加及删除的方法
2015/01/20 Javascript
跟我学习javascript的基本类型和引用类型
2015/11/16 Javascript
javascript从作用域链谈闭包
2020/07/29 Javascript
vue.js实现刷新当前页面的方法教程
2017/07/05 Javascript
Vue + better-scroll 实现移动端字母索引导航功能
2018/05/07 Javascript
如何理解Vue的v-model指令的使用方法
2018/07/19 Javascript
浅谈TypeScript 用 Webpack/ts-node 运行的配置记录
2019/10/11 Javascript
[01:11:35]Liquid vs LGD 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
跟老齐学Python之list和str比较
2014/09/20 Python
Python 搭建Web站点之Web服务器与Web框架
2016/11/06 Python
OpenCV图像颜色反转算法详解
2019/05/13 Python
Python 占位符的使用方法详解
2019/07/10 Python
Python中的self用法详解
2019/08/06 Python
Python多线程threading创建及使用方法解析
2020/06/17 Python
HTML5制作3D爱心动画教程 献给女友浪漫的礼物
2014/11/05 HTML / CSS
Chantelle仙黛尔内衣美国官网:法国第一品牌内衣
2018/07/26 全球购物
美国Jeep配件购物网站:Morris 4×4 Center
2019/05/01 全球购物
怎样在程序里获得一个空指针
2015/01/24 面试题
你对IPv6了解程度
2016/02/09 面试题
职高毕业生自我鉴定
2013/10/21 职场文书
英文版网络工程师求职信
2013/10/28 职场文书
布达拉宫的导游词
2015/02/02 职场文书
初中军训感想
2015/08/07 职场文书
军训决心书范文
2015/09/22 职场文书
解除合同协议书范本
2016/03/21 职场文书
导游词之舟山普陀山
2019/11/06 职场文书
python使用glob检索文件的操作
2021/05/20 Python
使用Pytorch实现two-head(多输出)模型的操作
2021/05/28 Python
Python中文纠错的简单实现
2021/07/07 Python
Python turtle编写简单的球类小游戏
2022/03/31 Python
SpringBoot整合minio快速入门教程(代码示例)
2022/04/03 Java/Android