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.
rangeis the upgraded version of Python 2'sxrange. Generators existed back in Python 2; they're quite orthogonal. I don't know whyyieldmakes 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.rangeis the equivalent ofxrange(although it has various impovements).rangeobjects are not really like generator objects at all.rangeobjects are specialized containers ofintobjects that can be represented by astrop,start, andstep. Generators are iterators.rangeobjects are not iterators.rangeobjects are sequences, generators are not sequences.rangeand the old, python 2rangefunctionality was removed. In Python 3, you would need to dolist(range(x))for the equivalent behavior of Python 2range(x)