Код генератора, который не работает должным образом в Python - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть следующий код итератора. Поскольку я создал отдельный класс, предназначенный для итераций по списку, если я помещу два последовательных оператора для операторов, которые я использовал для итерации по своему объекту, мне не нужно будет сбрасывать индекс вручную. Но при глобальном запуске он только один раз отображает элементы моего списка, а после нескольких итераций он перестает отображать что-либо, поэтому я думаю, что где-то сброс индекса происходит неправильно. Пожалуйста, используйте простой код и простые объяснения, потому что я новичок.

my_list = [1,2,3]    

class Iterator:
    def __init__(self,seq):
        self.seq = seq

    def __next__(self):
        if len(self.seq) > 0:
            return self.seq.pop(0)
        raise StopIteration


class Iterating:
    def __init__(self):
        pass

    def __iter__(self):
        return Iterator(my_list)

i_1 =Iterating()

for element in i_1:
    print(element)

print()

for element in i_1:
    print(element)

# why does this not work?

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Проблема в том, что метод pop изменяет список (см. документация ):

    def __next__(self):
        if len(self.seq) > 0:
            return self.seq.pop(0) # method pop(0) modifies list
        raise StopIteration

При создании нового экземпляра Iterator(my_list) переменная my_list передается по ссылке. Чтобы исправить это, вы можете создать копию my_list:

Iterator(my_list.copy())
0 голосов
/ 06 ноября 2019

Это потому, что когда вы перебираете свой Iterator, вы удаляете все элементы из вашего self.seq, поэтому, когда вы пытаетесь перебрать его во второй раз, вы перебираете пустой список. Вы можете создать временный список, из которого вы будете извлекать данные, и просто «пополнять» его каждый раз, когда завершите итерацию для дальнейшего использования.

class Iterator:
    def __init__(self,seq):
        self.seq = seq
        self.temp_seq = self.seq.copy()

    def __next__(self):
        if len(self.temp_seq) > 0:
            return self.temp_seq.pop(0)
        self.temp_seq = self.seq.copy()
        raise StopIteration
...