python学习之生成器(Generators)

来源:互联网 发布:python将矩阵转为图像 编辑:程序博客网 时间:2024/05/16 09:42

想要了解什么是生成器,那么我们先要知道什么是迭代器(iterators),迭代器是一个让程序员可以遍历一个容器(特别是列表)的对象。然而,一个迭代器在遍历并读取一个容器的数据元素时,并不会执行一个迭代。这句话可能不好理解,这句话里面包含几个概念我们先了解一下,然后再理解到底什么是生成器(Generators)。
可迭代对象(Iterable)
一个可迭代对象可以是python中的任意对象,只要改对象定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法。简单说,一个可迭代对象就是任意的对象,只要它能给我们提供一个迭代器(Iterator)。
迭代器(Iterator)
一个迭代器是一个任意对象,只要它定义了一个next(在python2中的叫法)或者__next__方法,那么它就是一个迭代器,是不是很简单。
下面我们了解一下什么叫迭代(iteration)。
迭代(Iteration)
用简单的话讲,他就是从某个地方(比如一个列表)取出一个元素的过程。当我们使用一个循环来遍历某个东西时,这就是一个迭代。迭代就是这个遍历过程本身的名字。


那么我们再来了解一下什么是生成器(generators)。
生成器也是一种迭代器,但是你只能对其迭代一次。这是因为他们并没有把所有的值存在内存中,而是在运行时生成值。你通过遍历来使用它们,要么用一个for循环,要么将他们传递给任意可以进行迭代的函数和结构。大多数时候生成器是以函数的形式来实现的,然而他们并不会返回一个值,而是yield(python中的一个关键字)出一个值。下面我们看一个简单的生成器的例子:

def generator_function():    for i in range(10):        yield ifor item in generator_function():    print(item)

以上的程序会输出为:
# Output: 0# 1# 2# 3# 4# 5# 6# 7# 8# 9
这只是一个简单的例子来帮着我们理解,实际上并不是很实用。生成器最佳的应用场景是:你不想同一时间将所有计算出来的大量结果集分配到内存中,特别是结果集中还包含循环的时候。因为这样做的时候会消耗大量的资源,在python2种很多标准函数都会返回一个列表,但是在python3种都修改成了生成器,因为生成器能够占用更少的资源。
我们看一下下面这个计算斐波那契数列的生成器:
# generator versiondef fibon(n):    a = b = 1    for i in range(n):        yield a        a, b = b, a + bfor x in fibon(1000000):    print(x)

用这种方式我们不用担心他会占用大量的资源,但是如果我们按照之前的方式来实现的话:
def fibon(n):    a = b = 1    result = []    for i in range(n):        result.append(a)        a, b = b, a + b    return result

这也许会在计算很大的参数时,用尽所有的资源,之前我们说过生成器使用一次迭代,但我们并没有测试过,在测试之前我们需要了解一下python的一个内置函数next()。它允许我们获取序列的下一个元素。
def generator_function():    for i in range(3):        yield igen = generator_function()print(next(gen))# Output: 0print(next(gen))# Output: 1print(next(gen))# Output: 2print(next(gen))# Output: Traceback (most recent call last):#            File "<stdin>", line 1, in <module>#         StopIteration

从上面的例子中,我们可以看到,当yield掉所有的值后,next函数触发了一个StopIteration的异常,这个异常告诉我们,所有的值都被yield完了。那么为什么我们执行for循环的时候不会抛出这个异常呢,因为for循环会自动捕捉到这个异常并且会自动停止调用next()。
同时python中的一些内置的数据类型也支持迭代,比如:
my_string = "Yasoob"next(my_string)# Output: Traceback (most recent call last):#             File "<stdin>", line 1, in <module>#         TypeError: str object is not an iterator

当我们试图直接对str对象执行next操作是,会发生TypeError的异常,这个异常说str对象不是一个迭代器。是的,因为他是一个可迭代对象,但不是一个迭代器,这意味着他虽然可以迭代,但是我们不能直接对其进行迭代操作。那么我们要怎么对其进行迭代呢,这是我们需要学习python的另一个内置函数iter()了,它将根据一个可迭代对象返回一个迭代器对象。比如:
my_string = "Yasoob"my_iter = iter(my_string)next(my_iter)# Output: 'Y'

这就是生成器和迭代器相关的知识啦,想要完全掌握这些知识,还需要我们在程序中经常运用哦!










0 0
原创粉丝点击