zoukankan      html  css  js  c++  java
  • python中的生成器(generator)总结

    1.实现generator的两种方式

    python中的generator保存的是算法,真正需要计算出值的时候才会去往下计算出值。它是一种惰性计算(lazy evaluation)。

    要创建一个generator有两种方式。

    第一种方法:把一个列表生成式的[]改成(),就创建了一个generator:

    >>> L = [x * x for x in range(10)]
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10))   # 注意把[]改成()后,不是生成一个tuple,而是生成一个generator
    >>> g
    <generator object <genexpr> at 0x1022ef630>

    第二种方式:在函数中使用yield关键字,函数就变成了一个generator。

    函数里有了yield后,执行到yield就会停住,当需要再往下算时才会再往下算。所以生成器函数即使是有无限循环也没关系,它需要算到多少就会算多少,不需要就不往下算。

    def fib():
    a, b = 0, 1
    while True:
    yield a
    a, b = b, a + b


    f = fib()
    print f, next(f), next(f), next(f)
    # <generator object fib at 0x7f89769d1fa0> 0 1 1

    如上例,第一次输出f,它就是一个generator,之后每次next,它就执行到yield a。

    当然其实平常很少用到next(),我们直接用for循环就可以遍历一个generator,其实for循环的内部实现就是不停调用next()。

    生成器可以避免不必要的计算,带来性能上的提升;而且会节约空间,可以实现无限循环(无穷大的)的数据结构。

    2.可迭代对象(Iterable)和迭代器(Iterator)的概念

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

    包括集合数据类型(listtupledictsetstr等)和生成器(generator)。

    可以使用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

    迭代器:Iterator。

    它表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

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

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

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

    Python的for循环本质上就是通过不断调用next()函数实现的,例如:

    for x in [1, 2, 3, 4, 5]:
        pass

    实际上完全等价于:

    # 首先获得Iterator对象:
    it = iter([1, 2, 3, 4, 5])
    # 循环:
    while True:
        try:
            # 获得下一个值:
            x = next(it)
        except StopIteration:
            # 遇到StopIteration就退出循环
            break

    3.itertools模块

    python的内置模块itertools提供了用于操作迭代对象的函数,非常方便实用。举一个例子:

    islice(iterable, [start, ] stop [, step]):

    创建一个迭代器,生成项的方式类似于切片返回值: iterable[start : stop : step],将跳过前start个项,迭代在stop所指定的位置停止,step指定用于跳过项的步幅。与切片不同,负值不会用于任何start,stop和step,如果省略了start,迭代将从0开始,如果省略了step,步幅将采用1.

    from itertools import islice
    
    
    def fib():
        a, b = 0, 1
        while True:
            yield a
            a, b = b, a + b
    
    
    f = fib()
    print list(islice(f, 10))
    # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
  • 相关阅读:
    (8)设计模式-桥接模式
    (6)设计模式-原型模式
    (5)设计模式-原型模式
    hdu4714树形DP+贪心(乱搞)
    hdu1059(背包dp二进制优化)
    uva12558 Egyptian Fractions (HARD version)(迭代深搜)
    hdu4135 Co-prime【容斥原理】
    BZOJ 1509[NOI 2003]逃学的小孩 树形dp
    bzoj1812 [Ioi2005]riv
    bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)
  • 原文地址:https://www.cnblogs.com/zywscq/p/5774567.html
Copyright © 2011-2022 走看看