Вопрос
Несмотря на то, что я читал об этом, я все еще не совсем понимаю, как __iter__
работает.Каково было бы простое объяснение?
Я видел def__iter__(self): return self
.Я не вижу, как это работает, или шагов по тому, как это работает.
Решение
Итератору необходимо определить два метода: __iter__()
и __next__()
(next()
в python2).Обычно сам объект определяет __next__()
или next()
метод, поэтому он просто возвращает себя в качестве итератора.Это создает повторяющийся это также само по себе является итератор.Эти методы используются for
и in
заявления.
Документы Python 3: docs.python.org/3/library/stdtypes.html#iterator-types
Документы Python 2: docs.python.org/2/library/stdtypes.html#iterator-types
Другие советы
Насколько я могу выразиться:
__ iter __
определяет метод класса, который будет возвращать итератор (объект, который последовательно возвращает следующий элемент, содержащийся в вашем объекте).
Объект итератора, который возвращает __ iter __ ()
, может быть практически любым объектом, если он определяет метод next ()
.
Метод next
будет вызываться с помощью операторов типа for ... in ...
для получения следующего элемента и next ()
должен вызывать исключение StopIteration
, когда больше нет элементов.
Что хорошего в этом, так это то, что он позволяет вам определять способ итерации вашего объекта, а __ iter __
предоставляет общий интерфейс, с которым каждая другая функция python знает, как работать. р>
Спецификации для def __iter __ (self):
: он возвращает итератор. Итак, если self
является итератором, return self
явно подходит.
" быть итератором " означает "наличие метода __ next __ (self)
" quot; (в Python 3; в Python 2 имя рассматриваемого метода, к сожалению, является простым next
, явно сбоем дизайна имени для специального метода).
В Python 2.6 и более поздних версиях лучший способ реализации итератора, как правило, заключается в использовании соответствующего абстрактного базового класса из стандартной библиотеки collection
module - в Python 2.6 этот код может быть (не забудьте вместо этого вызвать метод __ next __
в Python 3):
import collections
class infinite23s(collections.Iterator):
def next(self): return 23
экземпляр этого класса будет возвращать бесконечное количество копий 23
при повторной итерации (например, itertools.repeat (23)
), поэтому цикл должен быть прерван в противном случае. Дело в том, что создание подклассов collection.Iterator
добавляет правильный метод __ iter __
от вашего имени - здесь нет ничего сложного, но это хороший общий принцип (избегайте повторяющегося, стандартного кода, такого как стандартная однострочная итерация __ iter __
- в повторении нет добавленной стоимости и много вычитаемой стоимости! -).
Класс, поддерживающий метод __iter__, вернет экземпляр объекта итератора: объект, поддерживающий метод next () . Этот объект будет использоваться в выражениях «для» и "в".
В 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
в для
оператор.