python 中 yield 用法的总结

在MPGI4的第二次作业中,出现了 xrange() 相关用法,在查找其与 range 有什么不同时,发现了 generatoryield 等一系列概念,特此总结。


yield 的用法起源于对一般 functionreturn 的扩展。在一个 function 中,必须有一个返回值列于 return 之后,可以返回数字也可以返回空值,但是必须要有一个返回值,标志着这个 function 的结束。一旦它结束,那么这个 function 中产生的一切变量将被统统抛弃,有什么可以使一个 function 暂停下来,并且返回当前所在地方的值,当接收到继续的命令时可以继续前进呢?换个说法,就是 return 返回一个值,并且记住这个返回的位置。这个操作有点儿像

for x in range():
    pass

这个循环语句中 range() 这个函数干的事情,它给出一个数,当循环完一次以后再在前一个数的基础上拿出另外一个数。但是这里的函数其实是自动生成一个 list 然后从这个 list 第一个开始往后一个一个给出,那么这种方法的劣势显而易见——会有生成一个 list 。也就是说不管你的 for 循环用几回,它都会生成这个 list (比如你有一个庞大的数据库,那么光是生成一个表单就需要很长时间,然而也许你要用的东西就在前几个,那么你建起这个检索目录远远超过你实际所需要的)。这时就是 xrange() 登场的时候了,它就是一个不需要建立 list 却一样完成任务的好命令。那么 xrange() 是什么呢?

xrange() 其实是一个 generator 生成器,不同于一般的 function,里面就包含着yieldgenerator 人如其名,是一个生成器,生成什么呢?不妨把它看作生成一组你需要的序列的函数,通常情况下我们只需要自然数这种简单的序列,但是如果让你生成一组斐波那契数列呢?这组数列是无穷的,你想沿着这个数列一直算下去,直到算到你满意的一个数,但是如果你也不知道这个数在哪里,那么你就不能提前给出一个这个数列,因为你不知道在哪里会停下来。面对这个问题时,最好的解决方法就是记住当前的数记住当前的地址,查看一个这个数符合不符合要求,如果不符合要求,那么继续从这个数/地址开始计算下一个斐波那契数字。这就是 yield 要干的事情了。(其实这么做的好处还有一个就是减少斐波那契数列的运算量,这个数列因为是自循环数列,所以如果按照循环算法的话需要很大的运算量,但是如果是采用动态纪录法的话,那么就会非常简单。这属于优化算法范畴,暂且按下不表。)下面就是斐波那契数列用 yield 的实现法:

# 斐波那契数列:每一个数都等于前两个数之和
def fib(to=10):
    curr = 0
    next = 1
    count = 0
    while count < to:
        yield curr
        curr = next
        next = curr + next
        count += 1

# 一个用法例子:每一个斐波那契数列的数加1
if __name__ == '__main__':
    for x in fib(20):
        print(x+1)
        
    

注意:yield 一旦被采用,那么def后面的代码会立马被认作是一个 generator 而不是一个 function,因为生成的是一个 generator,所以可以被用在 for in 这个循环语句中。而 generatorfunction 从本质上是不同的,两者的区别就涉及到了next()send()这两个函数的用法。

如果把这个python文件命名为fi.py,并运行之。那么可以瞬间得到结果:

☁  Desktop  python fi.py
1
2
3
5
9
17
33
65
129
257
513
1025
2049
4097
8193
16385
32769
65537
131073
262145

用这个方法可以自己研究很多有趣的数学问题,比如找出2万以内的质数之和,找出大于10的0次方,一次方,...,n次方的最小质数。你不需要建立一个很大的索引库,只需要一个一个数字算下去就好。

这篇Jeff的文章帮了我一些忙,但可能是我英语不好,虽然解释的很基础,但对于我来说,还是没有彻底理解yield 和与其配套的next()send()的用法,以至于我拼命想搞懂他们的用法和关系并且成功了,不过回过头来看,确实解释的很全面。我觉得这种基础全面式解释需要一个实际的用法例子来补充说明,从稍微高一点儿的地方,或者从另一个初学者的视角来解释他们,初学者并不要解释的太基础,因为初学者其实学编程语言时根本不基础,越往后学习才会涉及到编译器的某些基础概念,这也是这篇文章的立意之处。

未完待续:next()send()这两个函数的用法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容