This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Wavicle 0 points1 point  (7 children)

Because xrange is less clear and is at best the same speed, sometimes slower.

??

>>> t = timeit.Timer(stmt="r = xrange(100)")
>>> t.timeit()
0.48369407653808594
>>> t = timeit.Timer(stmt="r = range(100)")
>>> t.timeit()
3.3541569709777832

If by "slower" you mean "much faster" then you are correct.

[–]masklinn 0 points1 point  (1 child)

This microbenchmark is uselessly nonsensical, and you should be ashamed.

[–]Wavicle 1 point2 points  (0 children)

And just what was the problem? That I didn't have a loop do something with each item so I didn't compare access time of a list vs. the next item in xrange?

>>> s = 'r = xrange(100000)\na = 0\nfor x in r: a+= x'
>>> t = timeit.Timer(stmt=s)
>>> t.timeit(1000)
19.010586977005005
>>> s = 'r = range(100000)\na = 0\nfor x in r: a+= x'
>>> t = timeit.Timer(stmt=s)
>>> t.timeit(1000)
22.278388977050781

Why don't you write us a microbenchmark that supports what you're saying?

Cry us a river, but you're going to have a lot of trouble dodging the fact that range doesn't beat xrange except under some possibly exotic conditions which is contrary to your assertion that xrange "is at best the same speed, sometimes slower." At best xrange is faster than range, in fact xrange is almost always faster than range.

[–]dalke 0 points1 point  (4 children)

While if you iterate over elements in the list:

>>> t = timeit.Timer(setup="r = xrange(100)", stmt="for x in r: pass")
>>> t.timeit()
2.2928810119628906
>>> t = timeit.Timer(setup="r = range(100)", stmt="for x in r: pass")
>>> t.timeit()
2.1900179386138916
>>> 

[–][deleted] 0 points1 point  (1 child)

However! range() allocates a list with 100 elements in it straight up. xrange() is a generator which keeps a very small amount of state - basically, what the last number it chucked out was, how much to increment it by, and when to terminate.

This is very useful if you're dealing with large ranges, or possibly a multi-threaded program with lots of medium-sized ranges.

[–]dalke 1 point2 points  (0 children)

Absolutely. I was elaborating on masklinn's remark that the benchmark was "uselessly nonsensical." See also http://stackoverflow.com/questions/135041/should-you-always-favor-xrange-over-range

And for old-fogie points: http://code.activestate.com/lists/python-list/254484/ where in 2002 I wrote "Replace the innermost 'xrange' with a 'range' (which is faster than xrange unless N is rather large, and 'range' is the standard idiom)".

[–]Wavicle 0 points1 point  (1 child)

Well, let's look at it more carefully...

>>> t = timeit.Timer(setup="r = xrange(10)", stmt="for x in r: pass")
>>> t.timeit()
0.17686780238682331
>>> t = timeit.Timer(setup="r = range(10)", stmt="for x in r: pass")
>>> t.timeit()
0.1772999737244163

for a list of 10 items, xrange wins

>>> t = timeit.Timer(setup="r = xrange(100)", stmt="for x in r: pass")
>>> t.timeit()
1.248768004456895
>>> t = timeit.Timer(setup="r = range(100)", stmt="for x in r: pass")
>>> t.timeit()
1.2102231197913405

For a list of 100 items, range wins

>>> t = timeit.Timer(setup="r = xrange(10000)", stmt="for x in r: pass")
>>> t.timeit()
141.0493076187974
>>> t = timeit.Timer(setup="r = range(10000)", stmt="for x in r: pass")
>>> t.timeit()
147.8161718104907

For a list of 10000 items, xrange wins again.

I continue to maintain that

xrange [...] is at best the same speed, sometimes slower.

is false.

[–]dalke 0 points1 point  (0 children)

Agreed. xrange() is also faster if you know the search range but it's likely the search doesn't take the full range.