Что такое iterator, итерируемый и повторение?
Что такое "итерируемый", "итератор" и "итерация" в Python? Как они определены?
Смотрите также: Как создать базовый итератор?
Переведено автоматически
Ответ 1
Итерация - это общий термин для обозначения каждого элемента чего-либо, одного за другим. Каждый раз, когда вы используете цикл, явный или неявный, для перехода по группе элементов, это итерация.
В Python итерируемый и итератор имеют определенные значения.
iterable - это объект, у которого есть __iter__
метод, который возвращает итератор, или который определяет __getitem__
метод, который может принимать последовательные индексы, начиная с нуля (и вызывает an IndexError
когда индексы больше не действительны). Итак, iterable - это объект, из которого вы можете получить итератор.
Итератор - это объект с next
(Python 2) или __next__
(Python 3) методом.
Всякий раз, когда вы используете for
цикл или map
, или представление списка и т.д. В Python next
метод вызывается автоматически для получения каждого элемента из итератора, таким образом проходя процесс итерации.
Хорошим местом для начала изучения будет раздел итераторы в руководстве и раздел типы итераторов на странице стандартных типов. После того, как вы поймете основы, попробуйте раздел "Итераторы" руководства по функциональному программированию.
Ответ 2
Вот объяснение, которое я использую при обучении классам Python:
Итерируемый - это:
- все , что может быть зациклено (т. Е. вы можете зациклить строку или файл) или
- все, что может отображаться в правой части цикла for:
for x in iterable: ...
или - все , что вы можете вызвать с помощью
iter()
, которое вернет ИТЕРАТОР:iter(obj)
или - объект, который определяет,
__iter__
который возвращает новый ИТЕРАТОР, или у него может быть__getitem__
метод, подходящий для индексированного поиска.
ИТЕРАТОР - это объект:
- с состоянием , которое запоминает, где оно находится во время итерации,
- с
__next__
методом , который:- возвращает следующее значение в итерации
- обновляет состояние , указывая на следующее значение
- сигнализирует, когда это выполняется путем повышения
StopIteration
- и это самоизменяемый (это означает, что у него есть
__iter__
метод, который возвращаетself
).
Примечания:
__next__
Метод в Python 3 пишется как speltnext
в Python 2, и- Встроенная функция
next()
вызывает этот метод для переданного ей объекта.
Например:
>>> s = 'cat' # s is an ITERABLE
# s is a str object that is immutable
# s has no state
# s has a __getitem__() method
>>> t = iter(s) # t is an ITERATOR
# t has state (it starts by pointing at the "c"
# t has a next() method and an __iter__() method
>>> next(t) # the next() function returns the next value and advances the state
'c'
>>> next(t) # the next() function returns the next value and advances
'a'
>>> next(t) # the next() function returns the next value and advances
't'
>>> next(t) # next() raises StopIteration to signal that iteration is complete
Traceback (most recent call last):
...
StopIteration
>>> iter(t) is t # the iterator is self-iterable
Ответ 3
Приведенные выше ответы великолепны, но, как и большинство из того, что я видел, недостаточно подчеркивают различие для таких людей, как я.
Кроме того, люди склонны становиться "слишком питоническими", вводя раньше определения типа "X - это объект, у которого есть __foo__()
метод". Такие определения верны - они основаны на философии "утиного набора текста", но акцент на методах имеет тенденцию отвлекать внимание при попытке понять концепцию в ее простоте.
Итак, я добавляю свою версию.
На естественном языке,
- итерация - это процесс взятия по одному элементу за раз в ряду элементов.
В Python,
iterable - это объект, который, ну, в общем, итерируемый, что, проще говоря, означает, что его можно использовать при повторении, например, с
for
циклом. Как? С помощью iterator. Я объясню ниже.... в то время как iterator - это объект, который определяет, как на самом деле выполнять итерацию - в частности, какой следующий элемент. Вот почему у него должен быть
next()
метод.
Итераторы сами по себе также итерируемы, с тем отличием, что их __iter__()
метод возвращает один и тот же объект (self
), независимо от того, были ли его элементы использованы предыдущими вызовами next()
.
Итак , что думает интерпретатор Python , когда видит for x in obj:
оператор?
Смотрите,
for
цикл. Похоже на работу для итератора... Давайте возьмем один . ... Есть одинobj
парень, так что давайте спросим его."Мистер
obj
, у вас есть свой итератор?" (... вызываетiter(obj)
, который вызываетobj.__iter__()
, который с радостью выдает блестящий новый итератор_i
.)Хорошо, это было просто... Тогда давайте начнем итерацию. (
x = _i.next()
...x = _i.next()
...)
Поскольку Mr. obj
преуспел в этом тестировании (благодаря тому, что определенный метод вернул действительный итератор), мы награждаем его прилагательным: теперь вы можете называть его "iterable Mr. obj
".
Однако в простых случаях вам обычно не выгодно иметь iterator и iterable отдельно. Таким образом, вы определяете только один объект, который также является собственным iterator . (Python на самом деле не волнует, что _i
выданный by obj
не был таким уж блестящим, а только obj
сам по себе.)
Вот почему в большинстве примеров, которые я видел (и что сбивало меня с толку снова и снова), вы можете видеть:
class IterableExample(object):
def __iter__(self):
return self
def next(self):
pass
вместо
class Iterator(object):
def next(self):
pass
class Iterable(object):
def __iter__(self):
return Iterator()
Однако бывают случаи, когда вы можете извлечь выгоду из отделения iterator от iterable , например, когда вы хотите иметь одну строку элементов, но больше "курсоров". Например, когда вы хотите работать с "текущими" и "предстоящими" элементами, у вас могут быть отдельные итераторы для обоих. Или несколько потоков, извлекающих информацию из огромного списка: у каждого может быть свой собственный итератор для обхода всех элементов. Смотрите ответы @Raymond и @glglgl выше.
Представьте , что вы могли бы сделать:
class SmartIterableExample(object):
def create_iterator(self):
# An amazingly powerful yet simple way to create arbitrary
# iterator, utilizing object state (or not, if you are fan
# of functional), magic and nuclear waste--no kittens hurt.
pass # don't forget to add the next() method
def __iter__(self):
return self.create_iterator()
Примечания:
Я повторю еще раз: итератор не является итерабельным. Итератор нельзя использовать в качестве "источника" в
for
цикле. В первую очередь нуженfor
цикл__iter__()
(который возвращает что-то сnext()
).Конечно,
for
это не единственный цикл итерации, поэтому вышесказанное применимо и к некоторым другим конструкциям (while
...).Итератор
next()
может вызывать StopIteration, чтобы остановить итерацию. Однако в этом нет необходимости, он может выполнять итерации вечно или использовать другие средства.В приведенном выше "процессе мышления"
_i
на самом деле не существует. Я придумал это название.В Python 3 есть небольшое изменение.x:
next()
теперь должен вызываться метод (не встроенный)__next__()
. Да, так и должно было быть с самого начала.Вы также можете представить это так: iterable содержит данные, iterator извлекает следующий элемент
Отказ от ответственности: Я не являюсь разработчиком какого-либо интерпретатора Python, поэтому я действительно не знаю, что интерпретатор "думает". Приведенные выше размышления являются исключительно демонстрацией того, как я понимаю тему из других объяснений, экспериментов и реального опыта новичка в Python.
Ответ 4
Итерируемый объект - это объект, у которого есть __iter__()
метод. Возможно, он может повторяться несколько раз, например, list()
s и tuple()
s .
Итератор - это объект, который выполняет итерацию. Он возвращается с помощью __iter__()
метода, возвращает себя с помощью своего собственного __iter__()
метода и имеет next()
метод (__next__()
в 3.x).
Итерация - это процесс вызова этого next()
соответственно. __next__()
до тех пор, пока он не вызоветStopIteration
.
Пример:
>>> a = [1, 2, 3] # iterable
>>> b1 = iter(a) # iterator 1
>>> b2 = iter(a) # iterator 2, independent of b1
>>> next(b1)
1
>>> next(b1)
2
>>> next(b2) # start over, as it is the first call to b2
1
>>> next(b1)
3
>>> next(b1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> b1 = iter(a) # new one, start over
>>> next(b1)
1