range creates a list, so if you do range(1, 10000000)
it creates a list in memory with 10000000
elements.
xrange
is a generator, so it is a sequence object is a that evaluates lazily.
所以 xrange 可以优化内存的使用
For performance, especially when you're iterating over a large range, xrange() is usually better. However, there are still a few cases why you might prefer range():
-
In python 3, range() does what xrange used to do and xrange does not exist. If you want to write code that will run on both Python 2 and Python 3, you can't use xrange.
-
range() can actually be faster in some cases - eg. if iterating over the same sequence multiple times. xrange has to reconstruct the integer object every time, but range will have real integer objects. (It will always perform worse in terms of memory however)
-
xrange isn't usable in all cases where a real list is needed. For instance, it doesn't support slices, or any list methods.
iterator
is a more general concept: any object whose class has a next
method (__next__
in Python 3) and an __iter__
method that does return self
.
Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield
expressions (yield
statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator
.
You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides next
(and __iter__
and __init__
). Most often, a generator (sometimes, for sufficiently simple needs, a generatorexpression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.