https://blog.csdn.net/u014745194/article/details/70176117

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

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

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()

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

解释说明:

在本类的实现中,定义了一个_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–>生成器
作用:

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

1

注意事项:

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

1
    2

分类:

第一类:生成器函数:还是使用 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

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

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

如下案例加以说明:

# 一个列表
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)
---------------------  
作者:ITxiaoke  
来源:CSDN  
原文:https://blog.csdn.net/u014745194/article/details/70176117  
版权声明:本文为博主原创文章,转载请附上博文链接!

Python中生成器和迭代器的区别(代码在Python3.5下测试):的更多相关文章

  1. python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解

    python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...

  2. python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解

    一.生成器 1.什么是生成器? 在python中,一边循环一边计算的机制,称为生成器:generator. 2.生成器有什么优点? 1.节约内存.python在使用生成器时对延迟操作提供了支持.所谓延 ...

  3. python中生成器与迭代器

    可迭代对象:一个实现了iter方法的对象是可迭代的 迭代器:一个实现了iter方法和next方法的对象就是迭代器 生成器都是Iterator对象,但list.dict.str虽然是Iterable(可 ...

  4. python中生成器及迭代器

    列表生成式 列表生成式是python内部用来创建list的一种方法,其格式形如: L = [x*8 for x in range(10)] print(L) 此时会得到结果:[0, 8, 16, 24 ...

  5. Python中生成器和迭代器的功能介绍

    生成器和迭代器的功能介绍 1. 生成器(generator) 1. 赋值生成器 1. 创建 方法:x = (variable for variable in iterable) 例如:x = (i f ...

  6. python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器

    1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...

  7. python中生成器对象和return 还有循环的区别

    python中生成器对象和return 还有循环的区别 在python中存在这么一个关键字yield,这个关键字在项目中经常被用到,比如我写一个函数不想它只返回一次就结束那我们就不能用return,因 ...

  8. Python中生成器和yield语句的用法详解

    Python中生成器和yield语句的用法详解 在开始课程之前,我要求学生们填写一份调查表,这个调查表反映了它们对Python中一些概念的理解情况.一些话题("if/else控制流" ...

  9. python语法生成器、迭代器、闭包、装饰器总结

    1.生成器 生成器的创建方法: (1)通过列表生成式创建 可以通过将列表生成式的[]改成() eg: # 列表生成式 L = [ x*2 for x in range(5)] # L = [0, 2, ...

随机推荐

  1. 【Java】Java Queue的简介

    阻塞队列 阻塞队列有几个实现: ArrayBlockingQueue LinkedBlockingQueue PriorityBlockingQueue DelayQueue SynchronousQ ...

  2. 【iCore4 双核心板_FPGA】例程八:乘法器实验——乘法器使用

    实验现象: 程序运行时,绿色led闪烁(目前,具体的乘法器调用请参考iCore3乘法器例程) 核心代码: module multiplier_ctrl( input clk_25m, input rs ...

  3. SQL group BY 合并字段用逗号隔开

    1.关联多表后 根据某个字段作为分组条件,其他合并到新列中,效果如下图 --------> 代码: ),KOrderID) , , '') from VOrder2 tb group by KU ...

  4. c# 调用非托管c++dll 参数问题(转)

    在C#中调用C(C++)类的DLL的时候,有时候C的接口函数包含很多参数,而且有的时候这些参数有可能是个结构体,而且有可能是结构体指针,那么在C#到底该如何安全的调用这样的DLL接口函数呢?本文将详细 ...

  5. Java知多少(28)super关键字

    super 关键字与 this 类似,this 用来表示当前类的实例,super 用来表示父类. super 可以用在子类中,通过点号(.)来获取父类的成员变量和方法.super 也可以用在子类的子类 ...

  6. SPARKR,对RDD操作的介绍

    (转载)SPARKR,对RDD操作的介绍   原以为,用sparkR不能做map操作, 搜了搜发现可以. lapply等同于map, 但是不能操作spark RDD. spark2.0以后, spar ...

  7. 如何在Ubuntu 14.04 中使用Samba共享文件

    1.安装 Samba 和图形配置工具 sudo apt-get install samba samba-common system-config-samba python-glade2 gksu 2. ...

  8. 深入Java内存模型之阅读理解(1)

    Java内存模型的抽象 在java中,所有实例域.静态域和数组元素存储在堆内存中,堆内存在线程之间共享(本文使用“共享变量”这个术语代指实例域,静态域和数组元素).局部变量(Local variabl ...

  9. iOS开发-- 开发中遇到的问题汇总

    1. CUICatalog: Invalid asset name supplied: 今天写了加载图片,默认图片写的是[UIImage imageNamed:@""],之后就报下 ...

  10. MangoDB学习笔记

    01. 数据库操作 1. 查看当前数据库名称 db 2. 查看所有数据库名称,列出所有在物理上存在的数据库 show dbs; 3. 切换数据库,如果数据库不存在也并不创建,直到插入数据或创建集合时数 ...