zoukankan      html  css  js  c++  java
  • 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是永远不可能存储全体自然数的。

  • 相关阅读:
    阿里云“网红"运维工程师白金:做一个平凡的圆梦人
    3235 战争
    1291 火车线路(区间修改,区间最值)
    P3183 [HAOI2016]食物链
    P1189 SEARCH(逃跑的拉尔夫)
    P1794 装备运输_NOI导刊2010提高(04)
    P2347 砝码称重
    P1332 血色先锋队
    P1772 [ZJOI2006]物流运输
    P1038 神经网络
  • 原文地址:https://www.cnblogs.com/long5683/p/9300815.html
Copyright © 2011-2022 走看看