• Python基础(7)——迭代器&生成器


    1、列表生成式

    1 [i*2 for i in range(10)]
    2 [fun(i) for i in range(10)]

    2、生成器

     1 # Author Qian Chenglong
     2 
     3 #列表生成器
     4 a=(i*2 for i in range(10))
     5 #a[1]#只是将算法存储了,只有在调用时才会生成相应的数据,不能直接读取
     6 a.__next__()#生成器只能一个一个往后取,且只存储当前值
     7 
     8 #函数生成器
     9 
    10 # def fib(max):
    11 #     n,a,b = 0,0,1
    12 #     while n < max:
    13 #         print(b)
    14 #         a,b = b,a+b
    15 #         n += 1
    16 #     return 'done'
    17 
    18 #要把fib函数变成generator,只需要把print(b)改为yield b就可以了
    19 def fib(max):
    20     n,a,b = 0,0,1
    21     while n < max:
    22         #print(b)
    23         yield  b
    24         a,b = b,a+b
    25         n += 1
    26     return 'done'#异常时存储的消息
    27 
    28 g=fib(10)
    29 print(g.__next__())
    30 #这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间当需要再重新调用这个函数,从上次yield的下一句开始执行。
    31 
    32 #生成器保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误(异常)。
    33 
    34 #异常处理
    35 g = fib(6)
    36 while True:
    37      try:
    38         x = next(g)
    39         print('g:', x)
    40 
    41     except StopIteration as e:
    42         print('Generator return value:', e.value)
    43         break
    44 
    45 #通过生成器实现协程并行运算
    46 import time
    47 def consumer(name):
    48     print("%s 准备吃包子啦!" %name)
    49     while True:
    50        baozi = yield
    51 
    52        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
    53 
    54 
    55 def producer(name):
    56     c = consumer('A')
    57     c2 = consumer('B')
    58     c.__next__()
    59     c2.__next__()
    60     print("老子开始准备做包子啦!")
    61     for i in range(10):
    62         time.sleep(1)
    63         print("做了2个包子!")
    64         c.send(i)
    65         c2.send(i)#把i的值传给yield,并到下一个yield
    66 
    67 producer("Dragon")

    3、迭代器

    我们已经知道,可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型,如listtupledictsetstr等;

    一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

    可以使用isinstance()判断一个对象是否是Iterable对象:

    >>> from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('abc', Iterable)
    True
    >>> isinstance((x for x in range(10)), Iterable)
    True
    >>> isinstance(100, Iterable)
    False

    *可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

      一般来说:生成器就是迭代器,迭代器不一定是生成器(下面不用看了,越看越不懂)

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

    listdictstrIterable变成Iterator可以使用iter()函数:

    1 >>> isinstance(iter([]), Iterator)
    2 True
    3 >>> isinstance(iter('abc'), Iterator)
    4 True

    你可能会问,为什么listdictstr等数据类型不是Iterator

    这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

  • 相关阅读:
    Two strings CodeForces
    Dasha and Photos CodeForces
    Largest Beautiful Number CodeForces
    Timetable CodeForces
    Financiers Game CodeForces
    AC日记——整理药名 openjudge 1.7 15
    AC日记——大小写字母互换 openjudge 1.7 14
    AC日记——将字符串中的小写字母换成大写字母 openjudge 1.7 13
    AC日记——加密的病历单 openjudge 1.7 12
    AC日记——潜伏着 openjudge 1.7 11
  • 原文地址:https://www.cnblogs.com/long5683/p/9300815.html
Copyright © 2020-2023  润新知