2

I came across various post and study material for xrange and Python generators, but its been quite long that I never saw someone comparing these 2 things together.

Its clear that xrange is not accepted in python3+, but can we consider generators as upgraded version of Python 2 xrange?

Both uses a iterator objects, both uses next() call. But the advantage of generator I learnt, we could make it pause with "yield", which is no such such thing for xrange.

Please help me understand the concept of both, and in which sense they are different? Also why xrange had to deprecated?

5
  • 5
    Python 3's range is the upgraded version of Python 2's xrange. Generators existed back in Python 2; they're quite orthogonal. I don't know why yield makes any sense in the context of a range object; if you need a generator, you should be using a generator; if you need a range object, you should be using a range object. Commented Dec 9, 2020 at 17:43
  • 2
    In Python 3, range is the equivalent of xrange (although it has various impovements). range objects are not really like generator objects at all. range objects are specialized containers of int objects that can be represented by a strop, start, and step. Generators are iterators. range objects are not iterators. range objects are sequences, generators are not sequences. Commented Dec 9, 2020 at 17:47
  • So what is the cause of xrange deadend? Are they too hideous to carry on with some upgrades to 3+. Sorry for dumb questions, I never came across use of xrange much. Commented Dec 9, 2020 at 17:50
  • 1
    It's not dead, it's been implemented as the base range function Commented Dec 9, 2020 at 17:51
  • @AnkurParanjpe it isn't dead, the name was changed to range and the old, python 2 range functionality was removed. In Python 3, you would need to do list(range(x)) for the equivalent behavior of Python 2 range(x) Commented Dec 9, 2020 at 18:26

2 Answers 2

2

Both range and generator objects are examples of iterable objects.

A range is defined by a stopping value, with an optional starting value and optional step size allowed. The result is an iterable of integers. A range also supports operations (like containment) that are not necessarily supported by other iterables.

A generator is defined by a generator expression or a generator function, either of which results in an iterable of arbitrary values.

The iterable aspect of a range object can be simulated by a generator:

def myrange(stop, start=None, step=None):
    if start is not None:
        from_ = stop
        to_ = start
    else:
        from_ = 0
        to_ = stop

    if step is None:
        step = 1 if from_ < to_ else -1

    while from_ < to_:
         yield from_
         from_ += step

Then

>>> list(myrange(1, 10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1, 10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

As Python 2 reached end-of-life nearly a year ago, there's not much reason to go into range. Suffice it to say, in Python 2 range was a function that returned a list of integers, while xrange was a type whose value represents a list of integers. Python 3 did away with the function and reused the name for the type.

Sign up to request clarification or add additional context in comments.

Comments

1

Both uses a iterator objects, both uses next() call. But the advantage of generator I learnt, we could make it pause with "yield", which is no such such thing for xrange.

xrange does pause between iterations. Compare these 2 lines of Python 2 code:

>>> a = range(150000000)   # takes about 3 seconds and 5 GB on my machine
>>> b = xrange(150000000)   # instant on my machine

range actually goes ahead and build up the entire list in memory. You can verify this by seeing your system RAM usage go up when you enter it.

What xrange does is actually pausing/yielding between iterations. If we iterate over b in a for loop, it will just produce the first element (0) in its first iteration, then its second element (1) in its second, and so on.

Here is a way one could implement xrange as a generator:

def my_range(stop):
    start = 0
    while start < stop:
        yield start
        start += 1
>>> c = my_range(150000000)

Two notes here:

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.