msg97912 - (view) |
Author: Martin Manns (mm) |
Date: 2010-01-16 21:55 |
In the Python 2.6.4 documentation "2. Built-in Functions" at http://docs.python.org/library/functions.html, the section about the xrange function (paragraph "CPython implementation detail") contains the following code: islice(count(start, step), (stop-start+step-1)//step) However, count only accepts one parameter, so that this solution does not work. Furthermore, islice only accepts positive values for step. Therefore, the code does not work. I tested this with Python 2.5.4 and Python 2.6.4 on Debian Linux (AMD64). |
|
|
msg97917 - (view) |
Author: Florent Xicluna (flox) *  |
Date: 2010-01-16 22:56 |
Confirmed. The snippet works for 3.1 and 2.7a2. from itertools import count, islice irange = lambda start, stop, step: islice(count(start, step), (stop-start+step-1)//step) The documentation needs update for 2.6 only. This kind of snippet seems backward compatible for 2.6: irange = lambda start, stop, step: islice(count(start), 0, stop, step) |
|
|
msg97918 - (view) |
Author: Martin Manns (mm) |
Date: 2010-01-16 23:07 |
The new snippet does not work for me: >>> list(irange(-12, 20, 4)) [-12, -8, -4, 0, 4] I have attached code that seems to work. It is more than a snipped though. |
|
|
msg97921 - (view) |
Author: Florent Xicluna (flox) *  |
Date: 2010-01-16 23:37 |
Right. Insufficient test. This snippet looks better, if we provide a replacement for 2.6. >>> irange = lambda start, stop, step: islice(count(start), 0, stop-start, step) |
|
|
msg97922 - (view) |
Author: Martin Manns (mm) |
Date: 2010-01-16 23:50 |
The new snippet works better. >>> list(irange(-12, 20, 4)) [-12, -8, -4, 0, 4, 8, 12, 16] However, it does not like large or negative slices: >>> list(irange(-2**65,2**65,2**61)) Traceback (most recent call last): File "", line 1, in File "", line 1, in OverflowError: long int too large to convert to int >>> list(irange(32,2,-3)) Traceback (most recent call last): File "", line 1, in File "", line 1, in ValueError: Indices for islice() must be non-negative integers or None. Perhaps the documentation can mention that. |
|
|
msg97927 - (view) |
Author: Florent Xicluna (flox) *  |
Date: 2010-01-17 00:33 |
You will prefer this one. It is as fast as the 2.7 version. The restrictions are described in the itertools documentation. from itertools import count, takewhile irange = lambda start, stop, step: takewhile(lambda x: x<stop, (start+i*step for i in count())) >>> list(irange(-2**65,2**65,2**61)) [-36893488147419103232L, ... |
|
|
msg97928 - (view) |
Author: Florent Xicluna (flox) *  |
Date: 2010-01-17 01:09 |
If you need also negative steps: from itertools import count, takewhile def irange(start, stop, step): if step < 0: cond = lambda x: x > stop else: cond = lambda x: x < stop return takewhile(cond, (start + i * step for i in count())) |
|
|
msg97929 - (view) |
Author: Martin Manns (mm) |
Date: 2010-01-17 01:19 |
Great solution! Thank you |
|
|
msg99624 - (view) |
Author: Martin Manns (mm) |
Date: 2010-02-20 17:55 |
So could we replace "If a larger range is needed, an alternate version can be crafted using the itertools module: islice(count(start, step), (stop-start+step-1)//step)." by "If a larger range is needed, an alternate version can be crafted using the itertools module: takewhile(lambda x: x<stop, (start+i*step for i in count()))." |
|
|
msg102370 - (view) |
Author: Georg Brandl (georg.brandl) *  |
Date: 2010-04-05 11:48 |
Thanks, fixed in release26-maint r79796. |
|
|