我们通常会听说,在for循环中要使用range来代替xrange,xrange更能节省内存,先来看一下这两个的实现:
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会预先生成范围内所有的整数,存入一个List中,然后返回List,我们知道List的append的操作是额外消耗内存的。
- xrange不会预先生成所有的数字,通过yield,每次被请求时,yield只会生成并返回一个对象,当超出range时,StopIteration会抛出。从内存看,一个N个元素的loop,相比xrange,range会多消耗N倍的内存。
- 迭代器,我们知道loop需要一个迭代器,然后不断调用next(),知道StopIteration。
- 使用range的流程是:创建一个完整的List,返回List,调用List的iter函数,返回一个迭代器。事实上,我们只需要一个迭代器,但是却创建了一个列表...
- 使用xrange的流程是:xrange会直接返回一个迭代器。我们可以看到range的流程更为复杂,做了很多额外的操作,消耗的计算和内存资源更多。
- 使用range时,这个预先分配List内存很要命,比如,range(100000000)会分配800MB内存...对于一个C developer来说,吓死了。
>>> import sys
>>> a = range(100000000)
>>> sys.getsizeof(a)
800000072
>>>