Как создать класс итератора в python, который будет выполнять итерации по входным данным в обратном порядке?

#python-3.x #class #iterator #iterable

#python-3.x #класс #итератор #итеративный

Вопрос:

Мне нужно создать класс итератора, который будет выполнять итерации по входным данным в обратном порядке. В значительной степени мне нужно повторить следующий код, используя class.

 def reverse(iterable)
    rev = len(iterable) - 1
    while rev >= 0:
        yield iterable[rev]
        rev -=1
  

Код должен работать примерно так:

 >>> nums = [1, 5, 6]
>>> ex = RevIter(nums)
>>> iter(ex) is ex
True
>>> next(ex) == 6
True
>>> next(ex)
5
>>> next(ex)
1
  

Мой код пока не работает:

 class RevIter:

    def __init__(self,iterable):        
        self.iterable = iterable
   
    def __next__(self):        
        rev = len(iterable) - 1        
        while rev >=0:            
        yield iterable[rev]            
        rev -= 1
  

ПРИМЕЧАНИЕ: я не могу использовать какие-либо встроенные функции, такие как reverse() или iter()

Ответ №1:

__next__ Метод в итерируемом классе сам по себе не является генератором — это простая функция, которая возвращает значение, вызываемое как часть протокола итератора.

Это __iter__ специальный класс, который при необходимости может быть генератором и функцией yield . Но тогда, если вы вызываете iter(myinstance) , __iter__ будучи функцией-генератором (т. Е. Функцией, Имеющей yield ключевое слово), iter Вызов создаст новый итерируемый экземпляр, который отличается от myinstance

Чтобы mysinstance is iter(myinstance) деталь работала, вы должны иметь iter метод, который возвращает self . И __next__ метод, который вернет следующий желаемый элемент.

 class RevIter:

    def __init__(self,iterable):        
        self.iterable = list(iterable)
        self.index = len(self.iterable)

    def __iter__(self):
        # if you want the instance to be able to reset the iteration,
        # redefine "self.index" here.
        # self.index = len(self.iterable)
        # this is what "iter(instance)" becomes:
        return self
   
    def __next__(self):        
        self.index -= 1
        if self.index < 0:
             raise StopIteration()
        return self.iterable[self.index]
  

Комментарии:

1. извините, в итоге я все сделал. Обычно я должен просто дать вам подсказку, когда нужно выполнить упражнение, но вам все равно понадобится информация о том, что __iter__ делает метод.

Ответ №2:

Вы не можете использовать yield в __next__ специальном методе, yield зарезервирован для генераторов.

Вот подсказка для реализации:

 class RevIter:
    def __init__(self, iterable):        
        self.iterable = iterable
        self.index = len(iterable)
   
    def __next__(self):
        # Maybe update self.index to prepare it for the next element?
        return # Maybe return something using the iterable and the index?
  

Чтобы подумать о том, как должно происходить обновление, представьте, что при переходе по списку из 5 элементов индексы будут (по порядку)

 4, 3, 2, 1, 0