zoukankan      html  css  js  c++  java
  • Day 3-6 生成器&迭代器

    ---恢复内容开始---

    列表生成式:

    1 list = [i*i for i in range(20)]  # 这就是一个列表生成式
    2 print(list)
    3 # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]
    4 list1 = [i if i < 8 else i*i  for i in range(10,20)]   # 可以进行三元运算.
    5 print(list1)
    6 # [110, 132, 156, 182, 210, 240, 272, 306, 342, 380]

    生成器:在Python中,这种一边循环一边计算的机制,称为生成器:generator。

    特性:

    1.只能往后面生成,不能返回到原来的值

    2.超过生成范围后,会停止生成,并报错。

    生成器的创建方式:

    1.通过列表生成式来创建   (i for i in range(100)

    2.通过函数来创建.

    a = [i for i in range(10000)]   # 列表生成式
    a2 = (i for i in range(10000))      # 这个就是一个生成器.但是怎么取数据呢?
    print(a2)                       # 我们print(a2),发现返回的是一个内存地址.那我们可以用next(a2)的方法来取数据.
    
    # 以下代码是在交互模式下进行的
    
    a2 = (i for i in range(1000))
    next(a2)
    0
    next(a2)
    1
    next(a2)
    2
    next(a2)
    3
    a3 = (i for i in range(5))
    
    
    next(a3)
    4
    next(a3)
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    StopIteration
    
    #我们手动调用的时候,调到最后一个的时候,再往下调就会出错.可以用for循环调用.就不会报错了
    for i  in a3:
        print(i)

     python2中 range=list

        xrange = 生成器

    python3 range =生成器

    没有xrange  

     yield:

     yield 和 return区别:

    yield  返回数据,并冻结当前的执行过程。

    return 返回并终止函数。

    当调用next的时候,唤醒冻结的函数执行过程。直到遇到下一次yield。

     函数有了yield之后:

    1.函数名加()就就得到了生成器。

    2.return 在生成器里,代表生成器终止,直接报错。 

    def fblq(num):
        n, a, b = 0, 0, 1
        while n < num:
            print('我在yield之前.')
            yield b     #把函数的执行过程冻结在这一步,并把b返回给外面的next().
            print(b)
            a, b = b, a+b
            n +=1
        else:
            return 0
    
    
    f = fblq(15)
    next(f)
    next(f)
    next(f)
    next(f)
    # 有yield,函数调用时,不会执行。只是生成了一个生成器对象。
    
    
    # 我在yield之前.
    # 1
    # 我在yield之前.
    # 1
    # 我在yield之前.
    # 2
    # 我在yield之前.
     1 # 函数的方式创建生成器
     2 
     3 def range1(n):
     4     count = 0
     5     while count <n:
     6         print(count)
     7         count +=1
     8         yield count   # 返回数据并冻结当前的执行状态.
     9 
    10 
    11 new = range1(10)
    12 next(new)
    13 next(new)
    14 new.__next__() # 和next(new)一样

    Send方法:

     1 def range1(n):
     2     count = 0
     3     while count <n:
     4         print(count)
     5         count +=1
     6         singe = yield count   # 返回数据并冻结当前的执行状态.
     7         if singe == "stop":   # 当接收的信号是stop时,就退出循环.
     8             break
     9 
    10 new = range1(100)
    11 
    12 next(new)
    13 next(new)
    14 new.__next__()
    15 new.send("stop")        #send 唤醒生成器继续执行并发送一个信号.next只唤醒生成器继续执行

    迭代器:

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

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

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

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

    判断一个对象是否是一个可迭代对象:

    from collections import Iterable
    li = [1,2,3,4,5,6,7,8,9,0]
    print(isinstance(li,Iterable))  # 判断一个对象是否是可迭代对象.是返回Trure,否返回False 

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

    生成器可以用for和next来取值.可迭代对象只能用for进行迭代取值.

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

    from collections import Iterator
    
    print(isinstance([],Iterator))  #  判断一个可迭代对象是不是一个迭代器
    print(isinstance((i for i in range(100)), Iterator))  #  目前只有生成器是迭代器.迭代器的一个重要的标志就是可以next

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

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

    from collections import Iterator
    
    print(isinstance(iter([]),Iterator))  #  判断一个可迭代对象是不是一个迭代器
    print(isinstance(iter("adfc"), Iterator))

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

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

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

    小结

    凡是可作用于for循环的对象都是Iterable类型;

    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

    集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

  • 相关阅读:
    P3531 [POI2012]LIT-Letters
    CF1338B Edge Weight Assignment
    CF118C Fancy Number
    New Year Contest
    P2587 [ZJOI2008]泡泡堂
    2021拓维游记
    CF1338C Perfect Triples
    gcc、g++、gdb安装
    vim教程之背键盘使我快乐
    Python起个头
  • 原文地址:https://www.cnblogs.com/lovepy3/p/8696926.html
Copyright © 2011-2022 走看看