range([start] ,end, [step])函数和xrange([start] ,end, [step])函数的相同点是都能创建一个列表。如:
>>> range(5)
[0, 1, 2, 3, 4]
>>> list(xrange(5))
[0, 1, 2, 3, 4]
但是,两者返回的原理是不同的。range函数返回的数据类型是一个list,而xrange函数返回的是一个生成器。
>>> l = range(5)
>>> x = xrange(5)
>>> type(l)
<type 'list'>
>>> type(x)
<type 'xrange'>
所以,xrange做循环的性能要比range要好,除非要返回的是一个列表。
# 注,此部分内容参考廖雪峰博客,详细请点击上面生成器的链接。
所谓生成器 (Generator),它的元素不像列表等对象的元素那样已经存在于内存中,它的元素要到运行的时候才生成。这样的好处是,它的元素个数可以不受内存的限制,而且还可以节省空间。
生成器可以按照以下方式来创建:
1.将列表生成式中的[ ]修改成( ),如:
>>> l = [ x*x for x in range(5)]
>>> type(l)
<type 'list'>
>>> g = ( x*x for x in range(5) )
>>> type(g)
<type 'generator'>
生成器的元素可以用next()方法来返回,当生成器的元素访问完后,再次运行next方法,会返回一个StopIteration错误
>>> g = ( x*x for x in range(5))
>>> g.next()
0
>>> g.next()
1
>>> g.next()
4
>>> g.next()
9
>>> g.next()
16
>>> g.next()
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
>>> g = ( x * x for x in range(5) )
>>> for n in g:
... print n
...
0
1
4
9
16
2.创建生成器的第二种方式是利用yield关键字。普通函数的执行是顺序执行,遇到return或者最后一行时就返回。
而变成generator的函数,每次执行next()时,遇到yield语句返回。再次执行时从上次返回的yield语句处继续执行。例:
>>> def odd():
... print 'step 1'
... yield 1
... print 'step 2'
... yield 2
... print 'stet 3'
... yield 3
...
>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
2
>>> o.next()
stet 3
3
>>> o.next()
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
一般我们都不会用next()来访问生成器中的元素,而是使用for循环来访问,如,斐波拉契数列的生成:
>>> def fib(max):
... n, a, b = 0, 0, 1
... while n < max:
... yield b
... a, b = b, a + b
... n = n + 1
...
>>> for n in fib(6):
... print n
...
1
1
2
3
5
8