Как работает __iter__? - PullRequest
       20

Как работает __iter__?

18 голосов
/ 23 октября 2009

Несмотря на то, что я читал об этом, я все еще не совсем понимаю, как работает __iter__. Что было бы простым объяснением?

Я видел def__iter__(self): return self. Я не вижу, как это работает или как это работает.

Ответы [ 5 ]

23 голосов
/ 23 октября 2009

Так просто, как я могу выразиться:

__iter__ определяет метод класса, который возвращает итератор (объект, который последовательно возвращает следующий элемент, содержащийся в вашем объекте).

Объект итератора, который возвращает __iter__(), может быть практически любым объектом, если он определяет метод next().

Метод next будет вызываться операторами типа for ... in ... для получения следующего элемента, а next() должен вызывать исключение StopIteration, когда элементов больше нет.

Что хорошего в этом, так это то, что он позволяет вам определять способ итерации вашего объекта, а __iter__ предоставляет общий интерфейс, с которым каждая другая функция python знает, как работать.

8 голосов
/ 23 октября 2009

Итератору необходимо определить два метода: __iter__() и __next__() (next() в python2). Обычно сам объект определяет метод __next__() или next(), поэтому он просто возвращает себя в качестве итератора. Это создает итерируемый , который также сам является итератором . Эти методы используются операторами for и in.

5 голосов
/ 23 октября 2009

Спецификации для def __iter__(self):: он возвращает итератор. Таким образом, если self является итератором, return self явно подходит.

«Быть ​​итератором» означает «иметь метод __next__(self)» (в Python 3; в Python 2 имя рассматриваемого метода, к сожалению, простое next вместо этого, явно сбой дизайна имени для специального метода ).

В Python 2.6 и выше, лучший способ реализовать итератор, как правило, использовать соответствующий абстрактный базовый класс из collections стандартной библиотеки module - в Python 2.6 код может быть ( не забудьте вызвать метод __next__ вместо этого в Python 3):

import collections

class infinite23s(collections.Iterator):
  def next(self): return 23

экземпляр этого класса будет возвращать бесконечное количество копий 23 при повторении (например, itertools.repeat(23)), поэтому в противном случае цикл должен быть завершен. Дело в том, что подклассы collections.Iterator добавляют правильный метод __iter__ от вашего имени - здесь нет ничего сложного, но есть хороший общий принцип (избегайте повторяющегося, стандартного кода, такого как стандартная однострочная итерация __iter__ - в повторение, нет добавленной стоимости и много вычитаемой стоимости! -).

2 голосов
/ 23 октября 2009

В Python итератор - это любой объект, который поддерживает протокол итератора. Частью этого протокола является то, что объект должен иметь метод __iter__(), который возвращает объект итератора. Я предполагаю, что это дает вам некоторую гибкость, чтобы объект мог передать обязанности итератора внутреннему классу или создать какой-то специальный объект. В любом случае, метод __iter__() обычно имеет только одну строку, и эта строка часто просто return self

Другая часть протокола - это метод next(), и именно здесь выполняется настоящая работа. Этот метод должен выяснить, создать или получить следующую вещь и вернуть ее. Может потребоваться отследить, где он находится, чтобы при следующем вызове он действительно возвращал следующую вещь.

Если у вас есть объект, который возвращает следующую вещь в последовательности, вы можете свернуть цикл for, который выглядит следующим образом:

myname = "Fredericus"
x = []
for i in [1,2,3,4,5,6,7,8,9,10]:
   x.append(myname[i-1])
   i = i + 1 # get the next i
print x

в это:

myname = "Fredericus"
x = [myname[i] for i in range(10)]
print x

Обратите внимание, что нигде нет кода, который получает следующее значение i, потому что range (10) - это объект, следующий за протоколом итератора, а понимание списка - это конструкция, которая использует протокол итератора.

Вы также можете напрямую использовать протокол итератора. Например, при написании сценариев для обработки файлов CSV я часто пишу следующее:

mydata = csv.reader(open('stuff.csv')
mydata.next()
for row in mydata:
    # do something with the row.

Я использую итератор напрямую, вызывая next() для пропуска строки заголовка, а затем косвенно использую его через встроенный оператор in в операторе for.

2 голосов
/ 23 октября 2009

Класс, поддерживающий метод __iter__, вернет экземпляр объекта итератора: объект, поддерживающий метод next () . Этот объект будет использоваться в выражениях «для» и «в».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...