На этом шаге мы рассмотрим получение и использование итераторов.
Для того чтобы превратить класс в итератор, нам следует переопределить в нем два специальных метода:
Если в классе одновременно определены методы __iter__() и __getitem__() (позволяет задать поведение при обращении к элементу контейнера), предпочтение отдается первому методу;
Для примера рассмотрим класс, хранящий строку и на каждой итерации возвращающий очередной ее символ, начиная с конца.
# Класс-итератор class ReverseString: def __init__(self, s): self.__s = s def __iter__(self): self.__i =0 return self def __next__(self): if self.__i > len(self.__s) - 1: raise StopIteration else: a = self.__s[-self.__i - 1] self.__i = self.__i + 1 return a
Проверим его в действии:
s = ReverseString ("Python") for a in s: print (a, end="")
Результат вполне ожидаем - строка, выведенная задом наперед:
nohtyP
Также мы можем переопределить специальный метод __len() __, который вернет количество элементов в последовательности. И, разумеется, мы можем переопределить специальные методы __str()__ и __rерr()__, возвращающие строковое представление итератора. (Все эти методы рассмотрены на 140 шаге.)
Перепишем код нашего класса-итератора, добавив в него определение методов __len()__ и __str__():
# Класс-итератор class ReverseString: def __init__(self, s): self.__s = s def __iter__(self): self.__i =0 return self def __next__(self): if self.__i > len(self.__s) - 1: raise StopIteration else: a = self.__s[-self.__i - 1] self.__i = self.__i + 1 return a def __len__(self): return len(self.__s) def __str__(self): return self.__s[::-1]
Теперь мы можем получить длину последовательности, хранящейся в экземпляре класса ReverseString, и его строковое представление:
s = ReverseString ("Python") print(len(s)) # Выведет: 6 print(str(s)) # Выведет: nohtyP
Результат работы приложения:
6
nohtyP
Со следующего шага мы начнем рассматривать контейнеры.