3

I had heard that range was a generator, then later I realized that it is not via this helpful post. While this post thoroughly explains how the __contains__ method works in constant time, I was not able to find any source code reference on how the lazy sequence is created. I tried to decipher the source code myself but having only basic knowledge in C, I am struggling. I believe the code snippet below is how the __iter__ works in range (do correct me if I'm wrong) - could you shed some light on how the lazy sequence is implemented here? Is it any different from the lazy sequence of a generator?

range_iter(PyObject *seq)
{
    rangeobject *r = (rangeobject *)seq;
    longrangeiterobject *it;
    long lstart, lstop, lstep;
    PyObject *int_it;

  long_range:
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
    if (it == NULL)
        return NULL;


    it->start = r->start;
    it->step = r->step;
    it->len = r->length;
    it->index = _PyLong_Zero;
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);
    return (PyObject *)it;
}
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
mysl
  • 1,003
  • 2
  • 9
  • 19
  • `iter(range(100))` leads to a `range_iterator` object, which is like a generator. – Daniel Jan 08 '20 at 20:13
  • 1
    @Daniel That's really not relevant, you can do the same thing with `list`, i.e. `iter([1,2,3])` will give you a `list_iterator` object, which is also "like a generator", in that it is an *iterator*. Note, I'm pretty sure if you do an `in` test on those iterators, it will always be O(N) rather than O(1) for using the `range` object directly. – juanpa.arrivillaga Jan 08 '20 at 20:40
  • 2
    A generator is not a class of types. `generator` is a *specific* type, one whose values are created by generator expressions like `(x for x in [1,2,3])` or by functions that use `yield` expressions. – chepner Jan 08 '20 at 21:23
  • `range` (as `list` does) returns an iterable, not an iterator. I.e. you can iterate on it several times, the loop shall not exhaust it like it would on an iterator. So @juanpa.arrivillaga 's comment above isn't fully correct. The reason is its `__iter__` method returns a new instance (as shown in @juanpa.arrivillaga 's answer below), not the same object every time (usually itself), like an iterator/generator does – Pynchia Jan 08 '20 at 21:36

0 Answers0