• 生成器&迭代器


    一.生成器

    在介绍生成器表达式之前,先看下列表表达式:

    1 >>> l = [i for i in range(50) if i % 2]        #生成数字50内所有奇数列表
    2 >>> l
    3 [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]

    生成器表达式和列表表达式一样,不过是()起来而不是[],成器表达式产生的生成器,它自身是一个可迭代对象,同时也是迭代器本身。例如:

     1 >>> gen = (i for i in range(50) if i % 2)
     2 >>> gen
     3 <generator object <genexpr> at 0x7f2f415eb2b0>
     4 >>> gen.__next__()   #使用next()方法可以访问下一个元素
     5 1
     6 >>> gen.__next__()
     7 3
     8 >>> gen.__next__()
     9 5
    10 >>> gen.__next__()
    11 7

    一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器

     1 def cash_out(amount):
     2     while amount >0:
     3         amount -= 1
     4         yield 1
     5         print("擦,又来取钱了。。。败家子!")
     6 ATM = cash_out(5)
     7 print("取到钱 %s 万" % ATM.__next__())
     8 print("花掉花掉!")
     9 print("取到钱 %s 万" % ATM.__next__())
    10 print("取到钱 %s 万" % ATM.__next__())
    11 print("花掉花掉!")
    12 print("取到钱 %s 万" % ATM.__next__())
    13 print("取到钱 %s 万" % ATM.__next__())
    14 print("取到钱 %s 万" % ATM.__next__()) #到这时钱就取没了,再取就报错了
    15 print("取到钱 %s 万" % ATM.__next__())

    yield的主要作用就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以重新调用这个函数,从上次yield的下一句开始执行。

    二。迭代器

    迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件

    特点:

    1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
    2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
    3. 访问到一半时不能往回退
    4. 便于循环比较大的数据集合,节省内存

    生成一个迭代器:

     1 >>> a = iter([1,2,3,4,5,6])
     2 >>> a.__next__()
     3 1
     4 >>> a.__next__()
     5 2
     6 >>> a.__next__()
     7 3
     8 >>> a.__next__()
     9 4
    10 >>> a.__next__()
    11 5
    12 >>> a.__next__()
    13 6
    14 >>> a.__next__()
    15 Traceback (most recent call last):
    16   File "<stdin>", line 1, in <module>
    17 StopIteration

    判断一个对象是否是iterable对象:

     1 from collections import Iterable
     2 >>> a
     3 <list_iterator object at 0x7f2f410ecfd0>
     4 >>> from collections import Iterable
     5 >>> print(isinstance(a,Iterable))
     6 True
     7 >>> print(isinstance({},Iterable))
     8 True
     9 >>> print(isinstance('fdsffdsf',Iterable))
    10 True
    11 >>> print(isinstance(100,Iterable))
    12 False

    总结:

    1.生成器都是Iterator对象,但list,tuple,str虽然是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象,因为python的Itertor表示的是一个数据流,可以被next。

    2.凡是可作用于for循环的对象都是Iterable类型;凡是可作用于next()函数都是Itertor

    3.经过测试生成器和列表生成器,两者占用cpu和运行速度不差上下,但是生成器只占用4g内存的0.3%,列表生成式占2.4%

  • 相关阅读:
    内部类概述和访问特点
    权限修饰符 权限
    抽象类和接口作为返回值类型的问题
    抽象类和接口作为形参问题
    jdbc:java数据库连接
    类与类、类与接口、接口与接口的关系
    接口
    抽象类
    多态
    继承中构造方法的关系
  • 原文地址:https://www.cnblogs.com/wenwei-blog/p/7238615.html
Copyright © 2020-2023  润新知