关于python中yield关键字的一些个人理解

之前在别人的一些code和python爬虫的学习中经常遇到这个关键字,一开始以为和循环没有什么区别,后来粗略地看了一下说明,结果越看越迷糊,加之发现了自己存在的知识漏洞,因此不得不好好学习一下相关概念


要理解yield,就必须先理解迭代(iteration)的相关概念.下边是一段摘自百度百科的定义:

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值

有两点需要注意:

逼近所需目标或结果,例如我们已经创建并初始化了一个列表(list)对象L,现在想在L中查找某个元素的值或者位置等,最简单的可以利用迭代从头对到尾对列表中的每个元素进行搜索,直到找到目标为止。

迭代得到的结果会作为下一次迭代的初始值:例如按照笛卡尔积的定义和运算法则,现在对于若干个集合A,B,C,D。。。(按照定义,它们为要么空集,要么为由有序关系对所组成)之间进行笛卡尔积的运算,即AxBxCxDx。。。,即要按照先后顺序和每一步所取得的结果去循环--先计算AxB,得到一个结果result1(也是一个集合),再让result1去xC,又得到了新的结果result2,再让result2去xC,以此类推。

另外一个例子就是设定一个变量并初始化,利用for循环让其不断自增,最后得到对应的结果。


看懂了迭代后,再来理解yield就不难了,实际上它就是生成器(generator)在python语言中的表述

关于生成器(generator)的概念(摘自wiki):

In computer science, a generator is a special routine that can be used to control the iteration behaviour of a loop. In fact, all generators areiterators.[1] A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values. However, instead of building an array containing all the values and returning them all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started processing the first few values immediately. In short, a generator looks like a function butbehaves like an iterator.

可以看出,与一般迭代相比,generator可以用于控制迭代的行为,同时也能返回对象。但与array能同时包含所有的value不同,generator一次只能包括一个,因此对内存的要求很低.另外与我们一开始接触它时的直观感受相同,generator看起来确实像一个函数,不过表现形式则是iterator。


以下代码实例转自廖雪峰的官网:

生成斐波那契数列

1.

简单也是传统的写法,利用while循环:

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        print b #python2标准的写法
        a, b = b, a + b #不用像c那样设置tmp变量,一步到位~
        n = n + 1

这里的话执行fab(5):

>>> fab(5)
1
1
2
3
5

与文章中评论的那样,代码的复用性较差,即无法保存中间生成的值。


2.利用列表来保存:

def fab(max): 
    n, a, b = 0, 0, 1 
    L = [] 
    while n < max: 
        L.append(b) 
        a, b = b, a + b 
        n = n + 1 
    return L 

可以通过for循环来获得返回值(列表)里边的元素

3.通过iterable对象来迭代

for i in range(1000): pass 

会导致生成一个 1000 个元素的 List,而代码:

for i in xrange(1000): pass

则不会生成一个 1000 个元素的 List,而是在每次迭代中返回下一个数值,内存空间占用很小。因为 xrange 不返回 List,而是返回一个 iterable 对象。

4.利用class,跳过。


5.使用yield

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        # print b
        a, b = b, a + b
        n = n + 1

调用及输出:

>>> for n in fab(5):
...     print n
...
1
1
2
3
5

看起来与2中的列表方法类似,但此例中的fab(5)则是一个生成器,调用fab(5)则会首先返回一个iterable对象,而不是去执行函数。之后在循环过程中每次都会执行fab函数内部的代码,到了yield b时,生成器处于暂停状态,fab函数返回一个迭代值。下次迭代时,代码从yield b的下一条语句继续执行,即完成对a,b的更新和n的自增,直到再次遇到yield。

也可以手动调用next方法(在python3中调用像f.next()的方法会shell提示attribute error,因为在新版本中该方法应该为next(f)),也可以逐一获得结果,最后会抛出StopIteration的异常,表示迭代完成。



参考资料:

1.https://baike.baidu.com/item/迭代/8415523?fr=aladdin

2.https://en.wikipedia.org/wiki/Generator_(computer_programming)

3.https://www.liaoxuefeng.com/article/001373892916170b88313a39f294309970ad53fc6851243000

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值