1

I have the following code which I wrote for a course which runs fine:

def reverse_iter(iterable):
    """Return a generator that yields items from iterable in reverse order"""
    last = len(iterable) - 1
    while last >= 0:
        yield iterable[last]
        last -= 1

The next part of the assignment is to turn this function into a class. I know this not practical but it is what is being asked. I have very limited knowledge about classes but I came up with the following code:

class ReverseIter:
    """Class whose instances iterate the initial iterable in reverse order"""
    def __init__(self, iterable):
        self.iterable = iterable

    def iterreverse(self):
        last = len(self.iterable) - 1
        while last >= 0:
            yield self.iterable[last]
            last -= 1  

nums = [1, 2, 3, 4]
it = ReverseIter(nums)
print(iter(it) is it)
print(next(it) == 4)
print(next(it))
print(next(it))
print(next(it))
print(next(it))

The output always reads TypeError: 'ReverseIter' object is not iterable. I hav eno idea why this is coming up. Any explanations or suggestions would be helpful. The output of the print statements above by the way should be True, True, 3, 2, 1, Stop Iteration respectively.

Fabian N.
  • 3,807
  • 2
  • 23
  • 46
user10200421
  • 207
  • 1
  • 3
  • 10
  • Possible duplicate of [Build a Basic Python Iterator](https://stackoverflow.com/questions/19151/build-a-basic-python-iterator) – Lev Zakharov Aug 09 '18 at 00:18
  • A quibble: You're assuming the `iterable` argument is a list, or at least something that can be `[]` subscripted like a list. But there are all sorts of [iterables](https://docs.python.org/3/glossary.html#term-iterable) that are not lists... some can't be subscripted, and some can't be passed to `len()`. A better name for that parameter would be [sequence](https://docs.python.org/3/glossary.html#term-sequence). – Kevin J. Chase Aug 09 '18 at 01:20

2 Answers2

5

An object is an iterator if it has a __next__ method, which is called to get the next item (and should raise StopIteration when it runs out), and __iter__ which returns an iterator (usually just self)

class ReverseIter:
    def __init__(self, sequence):
        self.sequence = sequence
        self.index = len(sequence) 
    def __iter__(self):
        return self
    def __next__(self):
        if self.index > 0:
            self.index -= 1
            return self.sequence[self.index]
        else:
            raise StopIteration
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • If it's an iterator, per the protocol, it *should* return self, although this isn't enforced: https://docs.python.org/3.7/library/stdtypes.html#iterator.__iter__ – juanpa.arrivillaga Aug 09 '18 at 00:36
1

you must implement the __next__ method, as code below.

 class ReverseIter:

     """Class whose instances iterate the initial iterable in reverse order"""

     def __init__(self, iterable):
         self.iterable = iterable

     def __iter__(self):
         last = len(self.iterable) - 1
         while last >= 0:
             yield self.iterable[last]
             last -= 1 
Fabian N.
  • 3,807
  • 2
  • 23
  • 46
郭志强
  • 11
  • 2