学习Scrapy的过程中碰到 yeild
这个关键字,我使用Python快半年了,还真的是第一次遇到这个关键字,於是我花了点时间研究後,终於明白它的作用了,怕下次看到时忘记,所以用这篇文将yield这个关键字重点整理一下。
如果想要印出0~100的平方时,我们可能会这样写。
powers = [x**2 for x in range(100)]
for x in powers:
print(x)
但这样有一个致命问题在於,必须把整个list都存放在记忆体中,100个元素可能还不成问题,但如果今天的对象是一百万笔资料,记忆体可能会承受不了,程序就崩溃了。
接下来就会说明yield要如何节省记忆体,但在此之前,先来谈谈Python的生成器(generator)。
生成器是一个可迭代的物件,可以放在for回圈的in前面,或者使用next()函数呼叫执行下一次迭代。
和列表的差别在於,生成器会保存上次纪录,并只有在呼叫下一层迭代的时候才载入记忆体执行。
所以将上面的例子改写成生成器,结果是一样的,却可以防止超过记忆体,注意我用的是 (
而不是 [
。
powers = (x**2 for x in range(100))
for x in powers:
print(x)
呼叫函数後,回传的并非数值,而是函数的生成器物件。
yield和return一样都会回传值并中断在目前位置,但最大不同在於yield在下次迭代时会从上次迭代的下一行接续执行,一直执行到下一个yield出现,如果没有下一个yield则结束这个生成器。而且接续上一个迭代前的变数不会改变,就是维持上次结束前的模样。
这部分我们来看下面这个例子:
def yield_test(n):
print("start n =", n)
for i in range(n):
yield i*i
print("i =", i)
print("end")
tests = yield_test(5)
for test in tests:
print("test =", test)
print("--------")
执行结果:
start n = 5
test = 0
--------
i = 0
test = 1
--------
i = 1
test = 4
--------
i = 2
test = 9
--------
i = 3
test = 16
--------
i = 4
end
StopIteration
(这边没有印出来),告诉主程序迭代已经结束了。看完上面例子後,应该会从原本朦朦胧胧到有点概念了吧,其实yield有点像侦错模式的中断点,只是多了中断时回传值而已。
def test():
print("start...")
while True:
throw = yield 10
print("throw:", throw)
p = test()
print(next(p))
print("-----------")
print(next(p))
print("-----------")
print(g.send(7))
print("-----------")
执行结果:
start...
10
-----------
throw: None
10
-----------
throw: 7
10
-----------
顺带一提,第一次迭代不可以send任何数值进去,因为没有上一个位置可以接收。
在Python 2.X中,有分range和xrange两种,range就像第一个例子,生成一个[0, 1, 2, ...]的list。xrange则像第二种例子,使用生成器减少记忆体消耗。
但在Python 3.X後range就等於xrange,使用type()检查会知道已经是range型态了。
print(type(range(10))) # <class 'range'>
如果开始学就是Python3.X,就不必在意这些细节,继续放心地用range吧!
<<: Rails基本介绍(一)一个实体 && Remove Duplicates from Sorted Array && Remove Element
>>: MacOS 透过 NVM 管理 Node.js 的版本管理器(Node Version Manager)
前言: 在经过两个礼拜的内容後,相信大家对写网页也有一定的基础了吧!这两个礼拜我们介绍很了多很好用...
简单自我介绍! 我是一位正在参加五倍红宝石勤奋转职的菜鸟工程师, 这也是我第一次参加IT铁人赛!同时...
大家好,我是长风青云。 今天我跟朋友讨论到我参加比赛这件事,她是一个完全没有程序基础的人。 她告诉我...
文章说明 文章分段 文章说明 deeplab的简单介绍、於我的意义 ep.1 tensorflow的...
.**电子密码本(ECB)**接受纯文本作为输入。 .**密码块链接(CBC)**接受“纯文本XOR...