Should you always favor xrange() over range()?

后端 未结 12 2013
后悔当初
后悔当初 2020-11-22 13:36

Why or why not?

相关标签:
12条回答
  • 2020-11-22 14:23

    Okay, everyone here as a different opinion as to the tradeoffs and advantages of xrange versus range. They're mostly correct, xrange is an iterator, and range fleshes out and creates an actual list. For the majority of cases, you won't really notice a difference between the two. (You can use map with range but not with xrange, but it uses up more memory.)

    What I think you rally want to hear, however, is that the preferred choice is xrange. Since range in Python 3 is an iterator, the code conversion tool 2to3 will correctly convert all uses of xrange to range, and will throw out an error or warning for uses of range. If you want to be sure to easily convert your code in the future, you'll use xrange only, and list(xrange) when you're sure that you want a list. I learned this during the CPython sprint at PyCon this year (2008) in Chicago.

    0 讨论(0)
  • 2020-11-22 14:23

    While xrange is faster than range in most circumstances, the difference in performance is pretty minimal. The little program below compares iterating over a range and an xrange:

    import timeit
    # Try various list sizes.
    for list_len in [1, 10, 100, 1000, 10000, 100000, 1000000]:
      # Time doing a range and an xrange.
      rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
      xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)
      # Print the result
      print "Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)
    

    The results below shows that xrange is indeed faster, but not enough to sweat over.

    Loop list of len 1: range=0.0003, xrange=0.0003
    Loop list of len 10: range=0.0013, xrange=0.0011
    Loop list of len 100: range=0.0068, xrange=0.0034
    Loop list of len 1000: range=0.0609, xrange=0.0438
    Loop list of len 10000: range=0.5527, xrange=0.5266
    Loop list of len 100000: range=10.1666, xrange=7.8481
    Loop list of len 1000000: range=168.3425, xrange=155.8719
    

    So by all means use xrange, but unless you're on a constrained hardware, don't worry too much about it.

    0 讨论(0)
  • 2020-11-22 14:24

    xrange() is more efficient because instead of generating a list of objects, it just generates one object at a time. Instead of 100 integers, and all of their overhead, and the list to put them in, you just have one integer at a time. Faster generation, better memory use, more efficient code.

    Unless I specifically need a list for something, I always favor xrange()

    0 讨论(0)
  • 2020-11-22 14:25

    range() returns a list, xrange() returns an xrange object.

    xrange() is a bit faster, and a bit more memory efficient. But the gain is not very large.

    The extra memory used by a list is of course not just wasted, lists have more functionality (slice, repeat, insert, ...). Exact differences can be found in the documentation. There is no bonehard rule, use what is needed.

    Python 3.0 is still in development, but IIRC range() will very similar to xrange() of 2.X and list(range()) can be used to generate lists.

    0 讨论(0)
  • 2020-11-22 14:30

    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.

    [Edit] There are a couple of posts mentioning how range() will be upgraded by the 2to3 tool. For the record, here's the output of running the tool on some sample usages of range() and xrange()

    RefactoringTool: Skipping implicit fixer: buffer
    RefactoringTool: Skipping implicit fixer: idioms
    RefactoringTool: Skipping implicit fixer: ws_comma
    --- range_test.py (original)
    +++ range_test.py (refactored)
    @@ -1,7 +1,7 @@
    
     for x in range(20):
    -    a=range(20)
    +    a=list(range(20))
         b=list(range(20))
         c=[x for x in range(20)]
         d=(x for x in range(20))
    -    e=xrange(20)
    +    e=range(20)
    

    As you can see, when used in a for loop or comprehension, or where already wrapped with list(), range is left unchanged.

    0 讨论(0)
  • 2020-11-22 14:33

    You should favour range() over xrange() only when you need an actual list. For instance, when you want to modify the list returned by range(), or when you wish to slice it. For iteration or even just normal indexing, xrange() will work fine (and usually much more efficiently). There is a point where range() is a bit faster than xrange() for very small lists, but depending on your hardware and various other details, the break-even can be at a result of length 1 or 2; not something to worry about. Prefer xrange().

    0 讨论(0)
提交回复
热议问题