#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