Вызов __iter__
неявно является преднамеренным; for
не знает, был ли ему передан итера tor или итера ble , и необходимо безоговорочно убедиться, что у него есть итера tor , который он делает, вызывая __iter__
. Если ваш объект уже является итератором, предполагается, что __iter__
идемпотентен, ничего не делает , но возвращает себя (тело должно быть только return self
). В существующем коде Python есть несколько тестов, которые обнаруживают итераторы путем тестирования iter(x) is x
, и если вы нарушите правила, сделав что-то иное, кроме возврата self
в свой пользовательский итератор, вы несете ответственность за неправильное поведение.
Дело в том, что то, что вы хотите делать, не имеет смысла. Либо напишите итератор (без __next__
и __iter__
, который возвращает новый итератор), либо напишите итератор, но если вы пишете итератор, вам нужно соблюдать правила для итераторов.
Просто для ясности, неизбежный порядок операций здесь:
reversed
вызывает __reversed__
, который теоретически должен вернуть новый обратный итератор (очень странно, что он возвращает существующий , теоретически прямой итератор) for
неявно вызывает __iter__
при любом возврате reversed
, чтобы убедиться, что это итератор (если __reversed__
были реализованы правильно, он вернул бы совершенно новый итератор, но вместо этого вы вызываете __iter__
для того же объекта) for
, а затем вызываете __next__
неявно для каждого элемента, пока не будет поднято StopIteration
Чтобы исправить это, попросите __reversed__
вернуть новый обратный итератор, а не self
; новый итератор __iter__
по-прежнему будет вызываться, но не тот, который был на исходном итераторе. Еще лучше, разделите свои реализации; то, что обратимо, не должно быть итератором. Просто сделайте __iter__
и __reversed__
обе функции генератора, которые производят все, что они должны произвести, и избавьтесь от __next__
, чтобы сделать ваш класс itera ble и обратимым, но не itera tor. .