zoukankan      html  css  js  c++  java
  • python------迭代器与生成器

    一 .   生成器

    1.介绍

    通过列表生成式,可以直接创建一个列表,但是受内存限制,列表容量是有限的。 

     a = [i*2 for i in range(10000)

     print (a)


    如果列表元素可以按照某种算法推算出来,是否可以在循环的过程中不断推算出后续的元素?
    这样就不必创建完整的list,从而俭省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器,generator.
    a = (i*2 for i in range(10000))
    for i in a:
    print (i)

    generator比较强大,但是如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

    比如:斐波那契数列,除了第一个和第二个数之外,任意的数都可有前面两个数相加得到(1,1,2,3,5,8,......)
     1 def fib(max):
     2     n, a, b = 0, 0, 1
     3     while n < max:   #n只是控制循环
     4         print(b)
     5         a, b = b, a + b
     6 
     7         # 相当于:t = (b, a + b)  (t是一个元组)
     8         #          a = t[0]
     9         #          b = t[1]
    10         #不等价于下面的
    11         #a = b   a = 1,b = 2,a = b, a = 2
    12         #b = a +b ,b = 2 + 2 = 4
    13 
    14         n=n+1
    15     return 'done'
    16 fib(100)  #生成100斐波那契数
    View Code
    
    
     1 def fib(max):
     2     n, a, b = 0, 0, 1
     3     while n < max:   #n只是控制循环
     4         #print(b)
     5         yield b      #就变成生成器了
     6         a, b = b, a + b
     7 
     8         # 相当于:t = (b, a + b)  (t是一个元组)
     9         #          a = t[0]
    10         #          b = t[1]
    11         #不等价于下面的
    12         #a = b   a = 1,b = 2,a = b, a = 2
    13         #b = a +b ,b = 2 + 2 = 4
    14 
    15         n=n+1
    16     return 'done'  #异常的时候打印的一个信息
    17 f = fib(10)  #生成100斐波那契数
    18 print(f.__next__())
    19 print(f.__next__())
    20 print("_________")   #函数想停就停,随意进出
    21 print(f.__next__())
    22 print(f.__next__())
    23 print(f.__next__())
    24 print("=====star loop======")
    25 for i in f:
    26     print(i)
    View Code

    补充:

    异常捕捉;

    还可以通过yield 实现在单线程的情况下实现并发运算的效果。

     1 import time
     2 def consumer(name):       #消费者
     3     print("%s 准备吃包子啦!" %name)
     4     while True:
     5        baozi = yield
     6 
     7        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
     8 
     9 c = consumer("xiaolai")
    10 c.__next__()    #只是为了打印print("%s 准备吃包子啦!" %name)
    11 
    12 def producer(name):      #生产者
    13     c = consumer('A')
    14     c2 = consumer('B')
    15     c.__next__()
    16     c2.__next__()    #唤醒yield
    17     print("老子开始准备做包子啦!")
    18     for i in range(10):
    19         time.sleep(1)
    20         print("做了1个包子,分两半!")
    21         c.send(i)
    22         c2.send(i)   #唤醒yield并且传值
    23 
    24 producer("shogou")
     

    2.说明:

         生成器,只有在调用时才会生成相应的数据。(只能用循环,不能像列表一样去切片))

        只记住当前位置;

        只有一个  .__next__方法。  (2.X版本中next())

    二. 迭代器

          可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型:list , tuple ,dict ,set ,str等;

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

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

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

    >>>from collections import Iterable
    >>>isinstance([], Iterable)
    True

    生成器不但可以作用于for循环,还可以被__next__()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

    可以被__next__()函数调用并不断返回下一个值的对象称为迭代器:Iterator.(是迭代器就有__next__()方法)

    >>>from collections import Iterator
    >>>isinstance([], Iterator )
    False

    生成器都是Iterator对象,但list, dict ,str 虽然是Iterable,却不是Iterator。把list, dict ,str 等Iterable变成Iterator可以使用iter()函数:

     a=[1,2,3]

    type (a)
    b = iter(a)
    b.__next__()

    小结:

          Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算,Iterator甚至可以表示一个无限大的数据流,例如全体自然数。使用list是永远不可能存储全体自然数的 。

       



  • 相关阅读:
    LeetCode OJ combine 3
    LeetCode OJ 229. Majority Element II
    Install Qualcomm Development Environment
    更改 terminal 開啟時,預設的路徑
    Establishing Android Build Environment
    Definition vs declaration
    declaration specifier, declarator, type specifier
    echo
    sed
    電路板上的 0Ω 電阻作用
  • 原文地址:https://www.cnblogs.com/bltstop/p/9465493.html
Copyright © 2011-2022 走看看