This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: range() is not a generator when used in for's
Type: Stage:
Components: Versions: Python 2.5
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: epsilon_da, ezio.melotti, mark.dickinson
Priority: normal Keywords:

Created on 2008-08-06 04:25 by epsilon_da, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (7)
msg70769 - (view) Author: Diego (epsilon_da) Date: 2008-08-06 04:25
Hi.

I am a debian lenny user so i am still using python 2.5 so i dont know 
how is this "bug" working on newer pythons. Please close it if you find 
that it doesnt exists.

It may not be a bug but.

I have maked an script to optimice minterms sums (This is electronics 
stuff to reduce the number of logic devices in an electronic design).
The algorithm depends exponentially on the number of bits in the input 
and the output. So to test it i have to generate 2**N_input_bits 
strings in a list. Each string being of N_input_bits+N_output_bits long.

The problem starts when N_input_bits is too much long. (from 25 and up)
The function range(2**N_input_bits) instantiates a list with all thoose 
numbers.

I have maked a test script to check it out:

import time

N=32

try:
  range(2**N)
  # range(): allocates N's integer's items in a list
except Exception, error:
  print "ERROR: ",error, "   Items=",N
  print

time.sleep(10)

def RANGE(a):
  # GENERATOR: Creates one output eachtime it is called.
  i=0
  while i<a:
    yield i
    i=i+1
  return

try:
  for x in RANGE(2**N):
    if not x%100:
      print x
except Exception, error:
  print "ERROR: ",error, "   Items=",N
  print
      

If i am not mistaken, "RANGE" will only take up one integer of memory 
each time instead of a complete list with "range()".
So it is better to use RANGE (a generator) with for's when i do not 
need to edit the list.
I think that range is mostly used in for's, so it will be a big improve 
to make the line:

for ... in range(....):

as a generator behavior and the normal range use:

alist = range(50)

as the same list.

This for line is very common in many programs and the content of the 
list can not be edited inside the for, it is only used by the for.
So, it can speed up python a little without requiring any changes.


Please if you consider this i not a bug or suggestion, or what ever, 
just close/delete/ignore the post. :)

Cheers.
Diego.
msg70770 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2008-08-06 05:51
In Python 2.x range() always return a list.
In Python 3.x it will return an iterator.

Other functions will be changed to return an iterator too (see
http://www.python.org/dev/peps/pep-3100/#built-in-namespace).
msg70772 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-08-06 07:26
The behavior of range is very unlikely to be changed in Python 2.x, for 
backwards compatibility reasons.

But it's a great idea!  So great, in fact, that it's already been 
implemented for Python 3.0.  :-)  There range() behaves like a generator 
(in all contexts);  if you really want a list, you'd write:

list(range(2**20))

Thanks!
msg70773 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-08-06 07:28
By the way, do you already know about xrange?

xrange([start,] stop[, step]) -> xrange object

Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand.  For looping, this is 
slightly faster than range() and more memory efficient.
msg70782 - (view) Author: Diego (epsilon_da) Date: 2008-08-06 13:24
2008/8/6 Mark Dickinson <report@bugs.python.org>:
>
> Mark Dickinson <dickinsm@gmail.com> added the comment:
>
> By the way, do you already know about xrange?
>
> xrange([start,] stop[, step]) -> xrange object
>
> Like range(), but instead of returning a list, returns an object that
> generates the numbers in the range on demand.  For looping, this is
> slightly faster than range() and more memory efficient.
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue3508>
> _______________________________________
>

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to int

4294967296L

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: range() result has too many items

Sadly so high numbers are longs and xrange seems to get an integer.
msg70783 - (view) Author: Diego (epsilon_da) Date: 2008-08-06 13:26
>>> a = xrange(2**32)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to int

>>> 2**32
4294967296L

>>> a=range(2**32)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
OverflowError: range() result has too many items



Sadly so high numbers are longs and xrange seems to get an integer.
msg70786 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-08-06 15:07
> Sadly so high numbers are longs and xrange seems to get an integer.

Something like that, yes:  the start, step and length of an xrange object 
are stored internally as C longs (just as Python ints are), and this is 
unlikely to change.

There's been quite a lot of recent discussion about the future of range 
and xrange:  see issue 2690, for example.

Maybe itertools.count would provide part of what you want?  Alternatively, 
if you've got a 64-bit machine you could try using a 64-bit build of 
Python---on platforms where a long is 64 bits, the limits should be 2**63 
instead of 2**31.
History
Date User Action Args
2022-04-11 14:56:37adminsetgithub: 47758
2008-08-06 15:07:46mark.dickinsonsetmessages: + msg70786
2008-08-06 13:26:01epsilon_dasetmessages: + msg70783
2008-08-06 13:24:11epsilon_dasetmessages: + msg70782
2008-08-06 07:28:08mark.dickinsonsetmessages: + msg70773
2008-08-06 07:26:36mark.dickinsonsetstatus: open -> closed
resolution: rejected
messages: + msg70772
nosy: + mark.dickinson
2008-08-06 05:51:07ezio.melottisetnosy: + ezio.melotti
messages: + msg70770
2008-08-06 04:25:30epsilon_dacreate