我們通常會(huì)聽(tīng)說(shuō),在for循環(huán)中要使用range來(lái)代替xrange,xrange更能節(jié)省內(nèi)存,先來(lái)看一下這兩個(gè)的實(shí)現(xiàn):
def range(start, stop, step=1):
numbers = []
while start < stop:
numbers.append(start)
start += step
return numbers
def xrange(start, stop, step=1):
while start < stop:
yield start
start += stop
- range會(huì)預(yù)先生成范圍內(nèi)所有的整數(shù),存入一個(gè)List中,然后返回List,我們知道List的append的操作是額外消耗內(nèi)存的。
- xrange不會(huì)預(yù)先生成所有的數(shù)字,通過(guò)yield,每次被請(qǐng)求時(shí),yield只會(huì)生成并返回一個(gè)對(duì)象,當(dāng)超出range時(shí),StopIteration會(huì)拋出。從內(nèi)存看,一個(gè)N個(gè)元素的loop,相比xrange,range會(huì)多消耗N倍的內(nèi)存。
- 迭代器,我們知道loop需要一個(gè)迭代器,然后不斷調(diào)用next(),知道StopIteration。
- 使用range的流程是:創(chuàng)建一個(gè)完整的List,返回List,調(diào)用List的iter函數(shù),返回一個(gè)迭代器。事實(shí)上,我們只需要一個(gè)迭代器,但是卻創(chuàng)建了一個(gè)列表...
- 使用xrange的流程是:xrange會(huì)直接返回一個(gè)迭代器。我們可以看到range的流程更為復(fù)雜,做了很多額外的操作,消耗的計(jì)算和內(nèi)存資源更多。
- 使用range時(shí),這個(gè)預(yù)先分配List內(nèi)存很要命,比如,range(100000000)會(huì)分配800MB內(nèi)存...對(duì)于一個(gè)C developer來(lái)說(shuō),嚇?biāo)懒恕?/li>
>>> import sys
>>> a = range(100000000)
>>> sys.getsizeof(a)
800000072
>>>