python 迭代器和生成器用法详解

python 迭代器

迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。

>>> l = range(2)
>>> i = iter(l)
>>> i
<listiterator object at 0x10a38d990>
>>> i.next()
0
>>> i.next()
1
>>> i.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。

# 当发生StopIteration异常,退出循环
for a in range(2):
    print a

常用的几个内建数据结构tuple、list、set、dict都支持迭代器,字符串也可以使用迭代操作。

你也可以自己实现一个迭代器,如上所述,只需要在类的iter方法中返回一个对象,这个对象拥有一个next()方法,这个方法能在恰当的时候抛出StopIteration异常即可。但是需要自己实现迭代器的时候不多,即使需要,使用生成器会更轻松。

#!/usr/bin/env python
# coding=utf-8

class test:
    def __init__(self, input_list):
        self.list = input_list
        self.i = 0

    def __iter__(self):
        return self
   
    def next(self):
        if self.i == len(self.list):
            self.i = 0
            raise StopIteration
        self.i += 1
        return  self.list[self.i - 1]
使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。

例如:

/* 把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了 */
for line in open("test.txt").readlines():
    print line

/* 这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行 */
for line in open("test.txt"):   #use file iterators
    print line
生成器
生成器的编写方法和函数定义类似,只是在return的地方改为yield。

生成器中可以有多个yield。当生成器遇到一个yield时,会暂停运行生成器,返回yield后面的值。当再次调用生成器的时候,会从刚才暂停的地方继续运行,直到下一个yield。

生成器自身又构成一个迭代器,每次迭代时使用一个yield返回的值。

>>> def gen():
...     yield 1
...     yield 2
...
>>> a = gen()
>>> a.next()
1
>>> a.next()
2
>>> a.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>
需要注意的是,生成器中不需要return语句,不需要指定返回值,在生成器中已经存在默认的返回语句

生成器表达式

(i for i in range(5))
// 返回迭代器
<generator object <genexpr> at 0x7ff3e8f0d960>
列表解析,返回list

[i for i in range(5)]
// 返回list
[0, 1, 2, 3, 4]

在这里存在一个问题,那就是range(5)会返回一个长度为5的数据,如果是range(1000)那么就会占用一个1000大小的数组空间;如果我们采用生成器,在需要的时候产生一个数字,那么空间的占用情况就会降低,这里我们可以使用xrange()函数来实现。

xrange
    函数说明:用法与range完全相同,所不同的是生成的不是一个数组,而是一个生成器。
xrange示例:

>>> xrange(5)
xrange(5)
>>> list(xrange(5))
[0, 1, 2, 3, 4]
>>> xrange(1,5)
xrange(1, 5)
>>> list(xrange(1,5))
[1, 2, 3, 4]
>>> xrange(0,6,2)
xrange(0, 6, 2)
>>> list(xrange(0,6,2))
[0, 2, 4]
所以xrange做循环的性能比range好,尤其是返回很大的时候,尽量用xrange吧,除非你是要返回一个列表

时间: 2024-09-18 18:05:30

python 迭代器和生成器用法详解的相关文章

python的迭代器与生成器实例详解_python

本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述:  迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.  1.1 使用迭代器的优点  对于原生支持随机访问的数据结构(如tuple.list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值).但对于无法随机访问的数据结构(比如se

Python中itertools模块用法详解_python

本文实例讲述了Python中itertools模块用法,分享给大家供大家参考.具体分析如下: 一般来说,itertools模块包含创建有效迭代器的函数,可以用各种方式对数据进行循环操作,此模块中的所有函数返回的迭代器都可以与for循环语句以及其他包含迭代器(如生成器和生成器表达式)的函数联合使用. chain(iter1, iter2, ..., iterN): 给出一组迭代器(iter1, iter2, ..., iterN),此函数创建一个新迭代器来将所有的迭代器链接起来,返回的迭代器从it

Python字典简介以及用法详解_python

#!/usr/bin/env python # -*- coding:utf-8 -*- """ 老规矩以下方法环境2.7.x,请3.x以上版本的朋友记得格式print(输出内容放入括号内) 字典的基本组成以及用法 dict = { key : value } dict[ key ] = value 首先来说说字典是由key键与value值一一对应来组成字典的基本结构 key键不能由list列表,dict字典等多元素命名, key是唯一属性又可以称一对一服务,key相同但只会

Python time时间模块用法详解

看Python time时间模块用法吧,具体的步骤细节如下文介绍. Python提供time时间模块需要单独引入 #推迟调用线程的运行,secs指秒数. time.sleep(secs) 时间戳 时间戳都以自从1970年1月1日午夜经过了多长时间来表示,时间间隔是以秒为单位的浮点小数. import time   # 引入time模块 print U"当前时间戳:",time.time() 输出结果: 当前时间戳: 1471487935.02 当前时间 time.localtime()

python中yield的用法详解

列表解析: [expr for iter_var in iterable if cond_expr] 生成器表达式: (expr for iter_var in iterable if cond_expr) 生成器最大的却别是它并不返回一个真正的数组 rows = [1,2,3,17]   def cols():     yield 56     yield 2     yield 1     abc = cols()   for i in abc:     print i   print ro

python队列模块Queue用法详解

一.初识Queue模块 Queue模块实现了多生产者.多消费者队列.它特别适用于信息必须在多个线程间安全地交换的多线程程序中.这个模块中的Queue类实现了所有必须的锁语义.它依赖于Python中线程支持的可用性:参见threading模块. 模块实现了三类队列:FIFO(First In First Out,先进先出,默认为该队列).LIFO(Last In First Out,后进先出).基于优先级的队列.以下为其常用方法: 先进先出  q = Queue.Queue(maxsize) 后进

Python中内置的日志模块logging用法详解_python

logging模块简介 Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用.这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志记录方式. logging模块与log4j的机制是一样的,只是具体的实现细节不同.模块提供logger,handler,filter,formatter. logger:提供日志接口,供应用代码使用.logger最长用的操作有两类:配置和发

php9个超全局变量的用法详解(二)

今天来讲一下$_GET()与$_POST(). 其实很容易理解,根据表面意思就可以看得出来,是获得post与get表单的数据,其实也正是如此,来点专业的话来讲, $_GET 变量是一个数组,内容是由 HTTP GET 方法发送的变量名称和值. $_GET 变量用于收集来自 method="get" 的表单中的值.从带有 GET 方法的表单发送的信息,对任何人都是可见的(会显示在浏览器的地址栏),并且对发送的信息量也有限制(最多 100 个字符).好,看个例子,上简单登录界面的代码: 登

php9个超全局变量的用法详解(一)

PHP 中的许多预定义变量都是"超全局的",这意味着它们在一个脚本的全部作用域中都可用.在函数或方法中无需执行 global $variable; 就可以访问它们. 这些超全局变量是: $GLOBALS $_SERVER $_GET $_POST $_FILES $_COOKIE $_SESSION $_REQUEST $_ENV 1.先看一下$GLOBALS,它是包含了全部变量的全局组合数组,什么意思呢,看一个c语言程序 int main() { int a = 3; void t(