Python中生成器和迭代器的区别详解

Python中生成器和迭代器的区别(代码在Python3.5下测试):

Num01–>迭代器

定义:

对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是python内置函数。

iter()函数会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。

迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的_next_方法(Python3中是对象的_next_方法,Python2中是对象的next()方法)。所以,我们要想构造一个迭代器,就要实现它的_next_方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现_iter_方法,而_iter_方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的_iter_方法返回自身self即可。

一些术语的解释:

1,迭代器协议:对象需要提供next()方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。
2,可迭代对象:实现了迭代器协议对象。list、tuple、dict都是Iterable(可迭代对象),但不是Iterator(迭代器对象)。但可以使用内建函数iter() ,把这些都变成Iterable(可迭代器对象)。
3,for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束

Python自带容器对象案例:

# 随便定义一个list
listArray=[1,2,3]
# 使用iter()函数
iterName=iter(listArray)
print(iterName)
# 结果如下:是一个列表list的迭代器
# <list_iterator object at 0x0000017B0D984278>

print(next(iterName))
print(next(iterName))
print(next(iterName))
print(next(iterName))#没有迭代到下一个元素,直接抛出异常
# 1
# 2
# 3
# Traceback (most recent call last):
# File "Test07.py", line 32, in <module>
# StopIteration

Python中一个实现了_iter_方法和_next_方法的类对象,就是迭代器,如下案例是计算菲波那切数列的案例

class Fib(object):
 def __init__(self, max):
  super(Fib, self).__init__()
  self.max = max

 def __iter__(self):
  self.a = 0
  self.b = 1
  return self

 def __next__(self):
  fib = self.a
  if fib > self.max:
   raise StopIteration
  self.a, self.b = self.b, self.a + self.b
  return fib

# 定义一个main函数,循环遍历每一个菲波那切数
def main():
 # 20以内的数
 fib = Fib(20)
 for i in fib:
  print(i)

# 测试
if __name__ == '__main__':
 main()

解释说明:

在本类的实现中,定义了一个_iter_(self)方法,这个方法是在for循环遍历时被iter()调用,返回一个迭代器。因为在遍历的时候,是直接调用的python内置函数iter() ,由iter()通过调用_iter_(self)获得对象的迭代器。有了迭代器,就可以逐个遍历元素了。而逐个遍历的时候,也是使用内置的next()函数通过调用对象的_next_(self)方法对迭代器对象进行遍历。所以要实现_iter_(self)_next_(self)这两个方法。

而且因为实现了_next_(self)方法,所以在实现_iter_(self)的时候,直接返回self就可以。

总结一句话就是:

在循环遍历自定义容器对象时,会使用python内置函数iter()调用遍历对象的_iter_(self)获得一个迭代器,之后再循环对这个迭代器使用next()调用迭代器对象的_next_(self)

注意点: _iter_(self)只会被调用一次,而_next_(self)会被调用 n 次,直到出现StopIteration异常。

Num02–>生成器

作用:

>延迟操作。也就是在需要的时候才产生结果,不是立即产生结果。

注意事项:

>生成器是只能遍历一次的。
>生成器是一类特殊的迭代器。

分类:

第一类:生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

如下案例加以说明:

# 菲波那切数列
def Fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  yield b
  a, b = b, a + b
  n = n + 1
 return '亲!没有数据了...'
# 调用方法,生成出10个数来
f=Fib(10)
# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
while True:
 try:
  x=next(f)
  print("f:",x)
 except StopIteration as e:
  print("生成器最后的返回值是:",e.value)
  break

第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。

如下案例加以说明:

# 一个列表
xiaoke=[2,3,4,5]
# 生成器generator,类似于list,但是是把[]改为()
gen=(a for a in xiaoke)
for i in gen:
 print(i)
#结果是:
2
3
4
5

# 为什么要使用生成器?因为效率。
# 使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。
# 如果你构造一个列表(list)的目的仅仅是传递给别的函数,
# 比如 传递给tuple()或者set(), 那就用生成器表达式替代吧!

# 本案例是直接把列表转化为元组
kk=tuple(a for a in xiaoke)
print(kk)
#结果是:
(2, 3, 4, 5)

# python内置的一些函数,可以识别这是生成器表达式,外面有一对小括号,就是生成器
result1=sum(a for a in range(3))
print(result1)
# 列表推导式
result2=sum([a for a in range(3)])
print(result2)

总结

以上就是本文关于Python中生成器和迭代器的区别详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

时间: 2018-02-07

举例讲解Python中的迭代器、生成器与列表解析用法

迭代器:初探 上一章曾经提到过,其实for循环是可用于任何可迭代的对象上的.实际上,对Python中所有会从左至右扫描对象的迭代工具而言都是如此,这些迭代工具包括了for循环.列表解析.in成员关系测试以及map内置函数等. "可迭代对象"的概念在Python中是相当新颖的,基本这就是序列观念的通用化:如果对象时实际保存的序列,或者可以再迭代工具环境中一次产生一个结果的对象,那就看做是可迭代的. >>文件迭代器 作为内置数据类型的文件也是可迭代的,它有一个名为__next_

Python中的迭代器与生成器高级用法解析

迭代器 迭代器是依附于迭代协议的对象--基本意味它有一个next方法(method),当调用时,返回序列中的下一个项目.当无项目可返回时,引发(raise)StopIteration异常. 迭代对象允许一次循环.它保留单次迭代的状态(位置),或从另一个角度讲,每次循环序列都需要一个迭代对象.这意味我们可以同时迭代同一个序列不只一次.将迭代逻辑和序列分离使我们有更多的迭代方式. 调用一个容器(container)的__iter__方法创建迭代对象是掌握迭代器最直接的方式.iter函数为我们节约一些

python生成器/yield协程/gevent写简单的图片下载器功能示例

本文实例讲述了python生成器/yield协程/gevent写简单的图片下载器功能.分享给大家供大家参考,具体如下: 1.生成器: '''第二种生成器''' # 函数只有有yield存在就是生成器 def test(i): while True: i += 1 res = yield i print(res) i += 1 return res def main(): t = test(1) # 创建生成器对象 print(next(t)) # next第一次执行从上到下,yield是终点 p

Python3中的列表生成式、生成器与迭代器实例详解

本文实例讲述了Python3中的列表生成式.生成器与迭代器.分享给大家供大家参考,具体如下: 列表生成式 Python内置的一种极其强大的生成列表 list 的表达式.返回结果必须是列表. 基本语法: [ 变量表达式 for 变量 in 表达式 ] 示例 a = [x ** 2 for x in range(1, 10)] b = [x * x for x in range(1, 11) if x % 2 == 0] c = [m + n for m in 'ABC' for n in '123

Python 中迭代器与生成器实例详解

Python 中迭代器与生成器实例详解 本文通过针对不同应用场景及其解决方案的方式,总结了Python中迭代器与生成器的一些相关知识,具体如下: 1.手动遍历迭代器 应用场景:想遍历一个可迭代对象中的所有元素,但是不想用for循环 解决方案:使用next()函数,并捕获StopIteration异常 def manual_iter(): with open('/etc/passwd') as f: try: while True: line=next(f) if line is None: br

浅谈Python中的可迭代对象、迭代器、For循环工作机制、生成器

1.iterable iterator区别 要了解两者区别,先要了解一下迭代器协议: 迭代器协议是指:对象需要提供__next__()方法,它返回迭代中的元素,在没有更多元素后,抛出StopIteration异常,终止迭代. 可迭代对象就是:实现了迭代器协议的对象. 协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for循环,sum,min,max函数等)通过迭代器协议访问对象,因此,for循环并不需要知道对象具体是什么,只需要知道对象能够实现迭代器协议即可. 迭代器(ite

深入讲解Python中的迭代器和生成器

在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知识了. 迭代器 迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和next()方法.其中__iter__()方法返回迭代器对象本身:next()方法返回容器的下一个元素,在结尾时引发StopIteration异常. __iter__()和next()

python生成器,可迭代对象,迭代器区别和联系

生成器,可迭代对象,迭代器之间究竟是什么关系? 用一幅图来概括: 1.生成器 定义生成器 方式一: //区别于列表生成式 gen = [x*x for x in range(5)] gen = (x*x for x in range(5)) print(gen) //Out:<generator object <genexpr> at 0x00000258DC5CD8E0> 方式二: def fib(): prev, curr = 0, 1 while True: yield cu

python 协程中的迭代器,生成器原理及应用实例详解

本文实例讲述了python 协程中的迭代器,生成器原理及应用.分享给大家供大家参考,具体如下: 1.迭代器理解 迭代器: 迭代器是访问可迭代对象的工具 迭代器是指用iter(obj)函数返回的对象(实例) 迭代器是指用next(it)函数获取可迭代对象的数据 迭代器函数(iter和next) iter(iterable)从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象 next(iterator) 从迭代器iterator中获取下一了记录,如果无法获取下一条记录,则触发

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

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

解析Python中的生成器及其与迭代器的差异

生成器 生成器是一种迭代器,是一种特殊的函数,使用yield操作将函数构造成迭代器.普通的函数有一个入口,有一个返回值:当函数被调用时,从入口开始执行,结束时返回相应的返回值.生成器定义的函数,有多个入口和多个返回值:对生成器执行next()操作,进行生成器的入口开始执行代码,yield操作向调用者返回一个值,并将函数挂起:挂起时,函数执行的环境和参数被保存下来:对生成器执行另一个next()操作时,参数从挂起状态被重新调用,进入上次挂起的执行环境继续下面的操作,到下一个yield操作时重复上面

老生常谈Python之装饰器、迭代器和生成器

在学习python的时候,三大"名器"对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?"装饰"从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行美化的一种行为,所谓"器"就是工具,对于python来说装饰器就是能够在不修改原始的代码情况下给其添加新的功能,比如一款软件上线之后,我们需要在不修改源代码和不修改被调用的方式的情况下还能为期添加新的功

Python函数装饰器实现方法详解

本文实例讲述了Python函数装饰器实现方法.分享给大家供大家参考,具体如下: 编写函数装饰器 这里主要介绍编写函数装饰器的相关内容. 跟踪调用 如下代码定义并应用一个函数装饰器,来统计对装饰的函数的调用次数,并且针对每一次调用打印跟踪信息. class tracer: def __init__(self,func): self.calls = 0 self.func = func def __call__(self,*args): self.calls += 1 print('call %s

python利用装饰器进行运算的实例分析

今天想用python的装饰器做一个运算,代码如下 >>> def mu(x): def _mu(*args,**kwargs): return x*x return _mu >>> @mu def test(x,y): print '%s,%s' %(x,y) >>> test(3,5) Traceback (most recent call last): File "<pyshell#111>", line 1, in

python函数装饰器用法实例详解

本文实例讲述了python函数装饰器用法.分享给大家供大家参考.具体如下: 装饰器经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计, 有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. #! coding=utf-8 import time def timeit(func): def wrapper(a): start = time.clock() func

python通过装饰器检查函数参数数据类型的方法

本文实例讲述了python通过装饰器检查函数参数数据类型的方法.分享给大家供大家参考.具体分析如下: 这段代码定义了一个python装饰器,通过此装饰器可以用来检查指定函数的参数是否是指定的类型,在定义函数时加入此装饰器可以非常清晰的检测函数参数的类型,非常方便 复制代码 代码如下: def accepts(exception,**types):     def check_accepts(f):         assert len(types) == f.func_code.co_argco

简单上手Python中装饰器的使用

Python的装饰器可以实现在代码运行期间修改函数的上下文, 即可以定义函数在执行之前进行何种操作和函数执行后进行何种操作, 而函数本身并没有任何的改变. 这个看起来很复杂, 实际上应用到了我之前说过的闭包的概念, 仔细看一看, 其实并不复杂. 首先, 我们先定义一个函数, 这个函数可以输出我的个人昵称: def my_name(): print "Yi_Zhi_Yu" my_name() # Yi_Zhi_Yu 那假如我需要在个人昵称输出前, 在输出我的个人uid呢, 当然, 要求是

python类装饰器用法实例

本文实例讲述了python类装饰器用法.分享给大家供大家参考.具体如下: #!coding=utf-8 registry = {} def register(cls): registry[cls.__clsid__] = cls return cls @register class Foo(object): __clsid__ = '123-456' def bar(self): pass print registry 运行结果如下: {'123-456': <class '__main__.F

Python的装饰器使用详解

Python有大量强大又贴心的特性,如果要列个最受欢迎排行榜,那么装饰器绝对会在其中. 初识装饰器,会感觉到优雅且神奇,想亲手实现时却总有距离感,就像深闺的冰美人一般.这往往是因为理解装饰器时把其他的一些概念混杂在一起了.待我抚去层层面纱,你会看到纯粹的装饰器其实蛮简单直率的. 装饰器的原理 在解释器下跑个装饰器的例子,直观地感受一下. # make_bold就是装饰器,实现方式这里略去 >>> @make_bold ... def get_content(): ... return '

python使用装饰器和线程限制函数执行时间的方法

本文实例讲述了python使用装饰器和线程限制函数执行时间的方法.分享给大家供大家参考.具体分析如下: 很多时候函数内部包含了一些不可预知的事情,比如调用其它软件,从网络抓取信息,可能某个函数会卡在某个地方不动态,这段代码可以用来限制函数的执行时间,只需要在函数的上方添加一个装饰器,timelimited(2)就可以限定函数必须在2秒内执行完成,如果执行完成则返回函数正常的返回值,如果执行超时则会抛出错误信息. # -*- coding: utf-8 -*- from threading imp

Python多层装饰器用法实例分析

本文实例讲述了Python多层装饰器用法.分享给大家供大家参考,具体如下: 前言 Python 的装饰器能够在不破坏函数原本结构的基础上,对函数的功能进行补充.当我们需要对一个函数补充不同的功能,可能需要用到多层的装饰器.在我的使用过程中,遇到了两种装饰器层叠的情况,这里把这两种情况写下来,作为踩坑记录. 情况1 def A(funC): def decorated_C(funE): def decorated_E_by_CA(*args, **kwargs): out = funC(funE)