Python学习散列:generator与yield

目录

前言

yield

1 递归函数中间值问题

2 返回迭代器解决中间值问题

generator

3 用生成器解决中间值问题

#4 对于yield和生成器的更详细的说明


前言

建议配合我的《Ruby学习散列:块与yield》一起观看。事实上,我会想要记下此节内容的原因主要也是觉得“在这两种表面上如此相似的语言中,对同一个关键字的定义如此的不同”这样的现象很有意思。

yield

yield是Python中的一个关键字,其用途可以看做“return”,只不过其返回的是其后的表达式的可迭代(iterable)对象

为了形象地说明其用途,我们举一个例子:

1 递归函数中间值问题

假设我们定义如下的函数gen,如下:

def gen():

    a,b=0,1

    while(a<100):

        b=b+a

        a=a+1

对于函数gen,如果我们要输出此函数执行过程中所有的b值,可以在函数体中添加print语句;而如果我们要将执行函数中运算出的所有b都交给另一个函数呢?

要解决这个问题,大多数人第一个想法必然是采用一个List来存储所有b的值,也就是多传入一个变量(或者在函数内使用grobal调用全局变量),并在运算之后使用append函数将结果加入列表。

但如果这样做,随着递归层数的加深,使用的列表的内存占用也会显而易见的变大。如果我们仅仅只是想使用一次List中的数据,它就会变得得不偿失。

2 返回迭代器解决中间值问题

既然使用List存储中间值会造成内存上的浪费,我们就应该寻找一个内存占用更低的方法。比如说,如果我们可以通过一个特殊的方法来中断函数的执行,在每一次调用数据的时候再计算下一步呢?这样就不用一次性保留所有运算结果了。

也就是说,如果我们的函数是可迭代的,就能达到减少内存占用的目的。在这种情况下,每个数据只计算一次,并且只使用一次,既没有重复运算的情况,又没有多余的内存占用。

我们可以使用yield关键字来达成上述的目的。

generator

Python中的generator即为生成器。其定义为使用了yield的函数,也就是说,yield在generator中被使用,并且返回一个iterable对象。

3 用生成器解决中间值问题

我们将函数修改成如下形式:

def gen():

    a,b=0,1

    while(a<100):

        b=b+a

        yield b

        a=a+1

与上面的函数对比,我们知道其只添加了一个”yield b”。根据generator的定义,运行函数gen会返回一个关于b的可迭代对象,我们可以用next()获取其下一个值,用send()对其本次迭代进行修改。

对于next与send函数的更详细说明请参考关于Python迭代器的定义。

#4 对于yield和生成器的更详细的说明

假设我们对于生成器函数gen有一个迭代器g,当我们调用gen()时,g被生成并且返回。在此之后,我们对gen的返回值进行迭代。当第一次调用g.next()时,执行了以下语句:

=>a,b=0,1

=>while {a=0}

=>b=b+a

=>yield b =>return b  

也就是说,在第一次执行next的时候,我们将函数执行直到遇见yield关键字。在遇见yield关键字之后我们返回其后的表达式的值,然后,我们中断此函数的执行(可以想象为IDE中的断点调试功能),直到下一次调用next或者send。

在之后的所有关于next和send的调用中,我们按照上一次中断时的所有设置(如果是send会改变一下yield后面的变量的值)继续执行函数,直到遇见一个yield并返回。

比如说我们执行第二个next,当然,我们知道执行完第一个next之后函数中的两个局部变量ab的值分别为0,1:

=>(a,b=0,1) #这是上次执行之后的ab值,我写在这里作为提示

=>a=a+1

=>while {a=1}

=>b=b+a

=>yield b =>return b

 我们可以看到,next之后函数又执行了一次循环,直到再次遇见了yield。此时的b为2,a为1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值