• 生成器、迭代器


    1、列表生成式
    a = [i**2 for i in range(10)]
    a为 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    2、生成器
    定义:一边循环一边计算后面元素的机制,称为生成器(generator)。
    生成器创建方法
      1、g = (i**2 for i in range(10))
    打印generation元素,需要用到next()方法
    next(g) 一次只能打印一个,要想再次打印就在next(g)
    当next(g)打印完最后一个元素后,在使用next(g),解释器则会报错。
    可以用for循环进行遍历,将所有元素都打印出来,也可以打印出自己需要的元素
    for i in g:
        if i > 10
            print(i)

      2、用函数来创建生成器,使用yield
      以斐波那契数列举例 0,1,1,2,3,5,8,13,21,34,55...
      当不使用生成器的:

    def fibo(n):
        before,now = 0, 1
        sum = 0
        count = 0
        while count < n:
            sum = before + now
            before = now
            now = sum
            count += 1
            print(before)

       如果使用生成器的话,只需要将print(before)变成yield before就可以了

    def fibo(n):
        before,now = 0, 1
        sum = 0
        count = 0
        while count < n:
            sum = before + now
            before = now
            now = sum
            count += 1
            yield before
    g_fibo = fibo(8)

    调用生成元素可以用g_fibo.__next__()
    当使用一次g_fibo.__next__(),函数运行就会暂停在yield位置,你就可以做其他的事情,当再次遇到g_fibo.__next__(),函数就会又开始执行,函数不断的暂停,开始。

    用生成器模拟并发编程

    import time
    def consumer(name):
        print("{0}准备开始吃东西".format(name))
        while True:
            meat = yield  # 将外面传过来的值赋值给meat
            print("肉{0}来了,肉被{1}吃了".format(meat, name))
    c1 = consumer("xu1")
    c2 = consumer("xu2")
    c1.__next__()
    c2.__next__()
    print("--------------大帅哥要开始做肉啦----------")
    for i in range(10):
        time.sleep(1)
        print("做了2盘肉")
        c1.send(i) # 将 i 传到yield处
        c2.send(i)

    调用send(x)给生成器传值时,必须确保生成器已经执行过一次next()调用, 这样会让程序走到yield位置等待外部第2次调用。

    3、迭代器


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

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

        一类是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

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

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

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

    >>> 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

    生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

    把list、dict、str等Iterable变成Iterator可以使用iter()函数:

    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True

    你可能会问,为什么list、dict、str等数据类型不是Iterator?

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

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

    小结

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

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

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


    --------借鉴于old_boy(老男孩教育)-------------------

  • 相关阅读:
    .Net 4.0 之并行运算(Parallel)(For、Foreach)
    【POJ】3494 Largest Submatrix of All 1’s
    【POJ】2676 Sudoku
    【POJ】3250 Bad Hair Day
    【SPOJ】11578 A Famous City
    【POJ】3740 Easy Finding
    【HUST】1017 Exact cover
    【POJ】3074 Sudoku
    【ZOJ】3209 Treasure Map
    【POJ】3076 Sudoku
  • 原文地址:https://www.cnblogs.com/zrxu/p/11580375.html
Copyright © 2020-2023  润新知