python中and和or的惰性求值特点_惰性求值和yield-Python
惰性求值
惰性求值(Lazy evaluation)是在需要時(shí)才進(jìn)行求值的計(jì)算方式。表達(dá)式不在它被綁定到變量之后就立即求值,而是在該值被取用的時(shí)候求值。
除可以得到性能的提升(更小的內(nèi)存占用)外,惰性計(jì)算的最重要的好處是它可以構(gòu)造一個(gè)無(wú)限的數(shù)據(jù)類(lèi)型。
yield的概念
yield的功能類(lèi)似于return,但是不同之處在于它返回的是生成器。
生成器
生成器是通過(guò)一個(gè)或多個(gè)yield表達(dá)式構(gòu)成的函數(shù),每一個(gè)生成器都是一個(gè)迭代器(但是迭代器不一定是生成器)。
如果一個(gè)函數(shù)包含yield關(guān)鍵字,這個(gè)函數(shù)就會(huì)變?yōu)橐粋€(gè)生成器。
生成器并不會(huì)一次返回所有結(jié)果,而是每次遇到y(tǒng)ield關(guān)鍵字后返回相應(yīng)結(jié)果,并保留函數(shù)當(dāng)前的運(yùn)行狀態(tài),等待下一次的調(diào)用。
由于生成器也是一個(gè)迭代器,那么它就應(yīng)該支持next方法來(lái)獲取下一個(gè)值。
# coding=utf8
# author=AaronChou
# 通過(guò)`yield`來(lái)創(chuàng)建生成器
def func():
for i in xrange(10):
yield i
# 通過(guò)列表來(lái)創(chuàng)建生成器
[i for i in xrange(10)]
# 調(diào)用如下
f = func()
print f # 此時(shí)生成器還沒(méi)有運(yùn)行
#
print f.next() # 當(dāng)i=0時(shí),遇到y(tǒng)ield關(guān)鍵字,直接返回
# 0
print f.next() # 繼續(xù)上一次執(zhí)行的位置,進(jìn)入下一層循環(huán)
# 1
# ...
print f.next()
# 9
print f.next() # 當(dāng)執(zhí)行完最后一次循環(huán)后,結(jié)束yield語(yǔ)句,生成StopIteration異常
# Traceback (most recent call last):
#?? File "", line 1, in
# StopIteration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
當(dāng)函數(shù)執(zhí)行結(jié)束的時(shí)候,generator自動(dòng)自動(dòng)拋出StopIteration的異常,表示迭代的結(jié)束,而在for循環(huán)中,我們不需要手動(dòng)的進(jìn)行處理異常,循環(huán)會(huì)自動(dòng)的正常結(jié)束。
除了next函數(shù),生成器還支持send函數(shù)。該函數(shù)可以向生成器傳遞參數(shù)。
# 通過(guò)`yield`來(lái)創(chuàng)建生成器
def func():
n = 0
while 1:
n = yield n? # 可以通過(guò)send函數(shù)向n賦值
f = func()
print f.next()? # 默認(rèn)情況下n為0
# 0
print f.send(1)? # n賦值1
# 1
print f.send(6)
# 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
注意fac不可迭代,而fac(5)可迭代
一個(gè)帶有yield的函數(shù)就是一盒g(shù)enerator,它和普通的函數(shù)不同,聲稱(chēng)一個(gè)generator看起來(lái)想函數(shù)調(diào)用,但是部執(zhí)行任何函數(shù)代碼,直到對(duì)其調(diào)用next()(注意在for循環(huán)中會(huì)自動(dòng)調(diào)用next)才開(kāi)始執(zhí)行。雖然執(zhí)行流程和普通函數(shù)一樣,但是每執(zhí)行到一個(gè)yield語(yǔ)句,就會(huì)中斷,并返回一個(gè)迭代值,下次執(zhí)行的時(shí)候從yield的下一個(gè)語(yǔ)句開(kāi)始執(zhí)行??雌饋?lái)像是一個(gè)函數(shù)在正常執(zhí)行的過(guò)程中被yield中斷了數(shù)次,每次中斷都會(huì)通過(guò)yield返回當(dāng)前迭代器的值。
yield的好處顯而易見(jiàn),把一個(gè)函數(shù)該寫(xiě)成generator就獲得了迭代能力,比起在類(lèi)的實(shí)例中保存狀態(tài)計(jì)算下一個(gè)next的值,更加使代碼清潔,而且執(zhí)行流程非常清晰
判斷是否為generator
方法是使用isgeneratorfunction來(lái)進(jìn)行判斷
from inspect import isgeneratorfunction
isgeneratorfunction(fac)
1
2
應(yīng)用
最經(jīng)典的例子,生成無(wú)限序列。
常規(guī)的解決方法是,生成一個(gè)滿(mǎn)足要求的很大的列表,這個(gè)列表需要保存在內(nèi)存中,很明顯內(nèi)存限制了這個(gè)問(wèn)題。
def get_primes(start):
for element in magical_infinite_range(start):
if is_prime(element):
return element
1
2
3
4
使用生成器就不需要返回整個(gè)列表,每次都只是返回一個(gè)數(shù)據(jù),避免了內(nèi)存的限制問(wèn)題。
def get_primes(number):
while True:
if is_prime(number):
yield number
number += 1
1
2
3
4
5
用生成器生成一個(gè)Fibonacci數(shù)列:
def fab(max):
a, b = 0, 1
while a < max:
yield a
a, b = b, a + b
for i in fab(20):
print i, ",",
1
2
3
4
5
6
7
8
9
10
迭代器(iterator),生成器(constructor),Yield
當(dāng)創(chuàng)建了一個(gè)列表,可以一個(gè)個(gè)的讀取它的每一項(xiàng),這叫做迭代器(iterator)。可以用在for...in...語(yǔ)句中的都是可迭代的:比如lists,strings,files…因?yàn)檫@些可迭代的對(duì)象你可以隨意的讀取所以非常方便易用,但是必須把它們的值放到內(nèi)存里,當(dāng)它們有很多值時(shí)就會(huì)消耗太多的內(nèi)存.
mylist = [x * x for x in range(3)]
for i in mylist:
print i
1
2
3
生成器(constructor)也是迭代器的一種,但是只能迭代它們一次,原因很簡(jiǎn)單,因?yàn)樗鼈儾皇侨看嬖趦?nèi)存里,它們只在要調(diào)用的時(shí)候在內(nèi)存里生成。
mygenerator = (x * x for x in range(3))
for i in mygenerator:
print i
1
2
3
生成器和迭代器的區(qū)別就是用()代替[],不能用for i in mygenerator第二次調(diào)用生成器:首先計(jì)算0,然后會(huì)在內(nèi)存里丟掉0去計(jì)算1,直到計(jì)算完4.
mygenerator = (x * x for x in range(3))
for i in mygenerator:
yield i * i
1
2
3
使用Yield時(shí),調(diào)用函數(shù)的時(shí)候,函數(shù)里的代碼并沒(méi)有運(yùn)行。函數(shù)僅僅返回生成器對(duì)象,然后,每當(dāng)for語(yǔ)句迭代生成器的時(shí)候你的代碼才會(huì)運(yùn)轉(zhuǎn)。節(jié)省了內(nèi)存空間。
Yield其實(shí)就是Python中應(yīng)用了惰性求值的思想,使得函數(shù)能夠建立可計(jì)算的無(wú)限列表而沒(méi)有妨礙計(jì)算的無(wú)限循環(huán)或大小問(wèn)題
參考:
http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
http://www.cnblogs.com/coder2012/p/4990834.html
總結(jié)
以上是生活随笔為你收集整理的python中and和or的惰性求值特点_惰性求值和yield-Python的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 我看中国软件---管理篇
- 下一篇: linux 软链接_Liunx 命令之链