Python: создание класса, который можно циклически повторять - PullRequest
0 голосов
/ 03 ноября 2018

Я хочу создать в Python класс, ведущий себя как список, но его можно циклически повторять пример использования:

myc = SimpleCircle()
print(len(myc))
j = iter(myc)
for i in range (0, 5):
    print(next(j))

это напечатает б с d а

код, который я пробовал до сих пор, приведен ниже Я знаю, что проблема с моим __next__

метод который, кстати, кажется проигнорированным, я могу использовать следующий, даже если я не реализую это

class SimpleCircle:
    def __init__(self):
        self._circle = ['a', 'b', 'c', 'd']
        self._l = iter(self._circle)


    def __len__(self):
        return len(self._circle)

    def __iter__(self):
        return (elem for elem in self._circle)

    def __next__(self):
        try:
            elem = next(self._l)
            idx = self._circle.index(elem)
            if idx < len(self._circle):
                return elem
            else:
                return self._circle[0]
        except StopIteration:
            pass

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Вот базовая реализация без itertools:

class CyclicIterable:
    def __init__(self, data):
        self._data = list(data)

    def __iter__(self):
        while True:
            yield from self._data

cycle = CyclicIterable(['a', 'b', 'c', 'd'])
for i, x in zip(range(5), cycle):
    print(x)

Обратите внимание, что нет необходимости реализовывать __next__, поскольку сам класс Cycle, как и list, , не является итератором. Чтобы явно извлечь из него итератор, вы пишете:

it = cycle.__iter__()
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))

Конечно, вы можете создавать столько итераторов, сколько захотите.

0 голосов
/ 03 ноября 2018

Это на самом деле уже существует с itertools.cycle, например:

from itertools import cycle

for x in cycle(['a', 'b', 'c', 'd']):
    print(x)

будет повторять элемент.

Далее вы перепутаете итератор и итератор, это часто разные вещи.

Как итерация, мы можем продолжать итерацию с self._circle:

class SimpleCircle:
    def __init__(self):
        self._circle = ['a', 'b', 'c', 'd']

    def __len__(self):
        return len(self._circle)

    def __iter__(self):
        if not self._circle:
            raise StopIteration
        while True:
            yield from self._circle

Или для итератора :

class CycleIterator:

    def __init__(self, iterable):
        self.iterator = iter(iterable)
        self.__next__ = self._iternext
        self.idx = 0
        self.list = []

    def _iternext(self):
        try:
            x = next(self.iterator)
            self.list.append(x)
            return x
        except StopIteration:
            self.__next__ = self._iterlist
            return self._iterlist()

    def _iterlist(self):
        try:
            return self.list[self.index]
        except IndexError:
            raise StopIteration
        finally:
            self.index = (self.index + 1) % len(self.list)
...