Из кода, который вы опубликовали, ясно, что вам не хватает того, что делает генератор , и как __iter__
и next
должны вести себя
Итак, начнем с протокола итератора. объект является итеративным, если он возвращает итератор при вызове его метода __iter__
, а итератор - это объект, имеющий метод next
, который можно вызывать ноль или более раз и в конечном итоге должен вызвать StopIteration
.
Для некоторых видов объектов весьма свойственно быть их собственными итераторами (которые имеют __iter__
return self
), но обычно это ограничивается объектами, которые каким-то образом сами представляют позицию внутри чего-либо. Например, встроенный объект file
является собственным итератором, поскольку файлы имеют внутреннюю позицию поиска (которой вы можете манипулировать с помощью file.seek()
и file.tell()
). Другие объекты, которые представляют совокупность коллекции, например list
, возвращают что-то отличное от себя.
Итак, ваше дерево действительно больше похоже на последнее, чем на первое; У него нет атрибута позиции, представляющего, на каком узле он находится; это все узлы одновременно, поэтому, вероятно, не должен иметь метод next()
; __iter__
нужно вернуть что-то еще.
Что приводит нас к генераторам. Когда обычная функция содержит оператор yield
, она автоматически вообще не является функцией, а является генератором. Разница в том, что когда вы вызываете функцию, выполняется ее тело (и, возможно, возвращает значение). Когда вы вызываете генератор, он немедленно возвращается, не выполняя тело вообще; вместо этого вы получаете итератор ! когда вы повторяете это, вызывается тело функции; переход к следующему yield
каждый раз, пока он, наконец, не вернется.
Итак, все вместе,
class t:
def __init__(self):
self.l = []
self.a = 0
def __iter__(self):
# first, yield everthing every one of the child nodes would yield.
for child in self.l:
for item in child:
# the two for loops is because there's multiple children, and we need to iterate
# over each one.
yield item
# finally, yield self
yield self
Но поскольку мы выполняем итерацию последовательности итераторов (а также еще одной вещи, self), itertools.chain
, как в принятом ответе, действительно имеет большой смысл.