Is there anyway to run a for loop with a range of over 13 characters? For example:
for i in range (1000000000000):
I know this won't work but is there any way it could?
Is there anyway to run a for loop with a range of over 13 characters? For example:
for i in range (1000000000000):
I know this won't work but is there any way it could?
Using xrange
can also give you Python int too large to convert to C long
Error as the number has to fit into a C long. To overcome this use itertools.count
to create you own range:
from itertools import count
def myx_range(start, end):
return iter(count(start).next, end)
If you wanted to use the same logic with python 3:
from itertools import count
def myx_range(start, end):
cn = count(start)
return iter(lambda: next(cn), end)
Or a while
loop:
from itertools import count
def myx_range(start, end):
while start < end:
yield start
start += 1
A long is 32bit
on windows so you are going to hit the limit using xrange
with a number that large.
If the bounds and step are within the range [-sys.maxsize-1, sys.maxsize), and the total number of elements is <= sys.maxsize
, then xrange
has you covered.
If not, itertools
provides the parts you need to completely reimplement xrange
(and efficiently too, pushing all the work to the C layer in CPython) for the purposes of generation (xrange
is a real object can be generated over and over and supports a few other features; this only generates, and only once per call):
from itertools import count, islice
def myxrange(stop, *args):
'''Replacement for xrange to generate ranges of arbitrarily large numbers efficiently
'''
start, step = 0, 1 # Defaults when only one argument passed
if args:
if len(args) > 2:
raise TypeError("myxrange expected at most 3 arguments, got {}".format(len(args)))
start = stop # When 2+ args passed, stop is really start
stop, step = (args + (1,))[:2] # Use step if given, otherwise 1
# islice slices x items, we need to calculate the number to slice
# from the bounds given
numitems = (stop - start + (step - (1 if step > 0 else -1))) // step
return islice(count(start, step), numitems)
The above is obviously slightly overkill to handle step
s other than the default 1; it could be simplified dramatically if step
support wasn't needed.
In CPython (the reference interpreter) this should run more efficiently than using Python level code (which requires repeated byte code execution); once initialized, islice
and count
do all their work at the C layer, which can dramatically improve performance. For example, compared to the while
based loop from the other answer, in ipython running on Python 2.7 on my machine:
>>> %timeit -r5 list(xrange(10, 2000))
100000 loops, best of 5: 15.2 μs per loop
>>> %timeit -r5 list(myxrange(10, 2000)) # Version in my answer
10000 loops, best of 5: 24.9 μs per loop
>>> %timeit -r5 list(myxrange2(10, 2000)) # Version using while from Padraig's answer
1000 loops, best of 5: 173 μs per loop
# Padraig's count based version takes 124 μs, though it could be optimized
# down to ~59 μs by changing it to the C layer version (though either
# version breaks if start > stop):
def myxrange(start, stop):
return iter(count(start).next, end)
Even with the overhead of mimicking xrange
s non-standard argument prototype, the overhead for the count
+islice
code is only about 50% over xrange
, which ain't half bad given that it actually handles scenarios xrange
can't.
Remember that there is a limit of minumum and maximum value to store in processor register. It means that not all modules can receive big numbers as arguments.