Приведенные выше ответы великолепны, но, как большинство из того, что я видел, не подчеркивайте различие достаточно для таких людей, как я.
Кроме того, люди имеют тенденцию становиться «слишком питоническими», помещая такие определения, как «X - это объект, который имеет __foo__()
метод» прежде. Такие определения являются правильными - они основаны на философии типизации уток, но при попытке понять концепцию в ее простоте основное внимание уделяется методам.
Поэтому я добавляю свою версию.
На естественном языке,
- итерация - это процесс одновременного взятия одного элемента в ряд.
В Python
итерируемый - это объект, который, иными словами, итерируемый, что проще говоря, означает, что его можно использовать в итерации, например, с for
циклом. Как? С помощью итератора . Я объясню ниже.
... в то время как итератор - это объект, который определяет, как на самом деле выполнять итерацию, в частности, что является следующим элементом. Вот почему у него должен быть
next()
метод.
Сами итераторы также являются итеративными, с той разницей, что их __iter__()
метод возвращает один и тот же объект ( self
), независимо от того, были ли его элементы использованы предыдущими вызовами next()
.
Так что же думает интерпретатор Python, когда видит for x in obj:
оператор?
Смотри, for
петля. Похоже, работа для итератора ... Давайте возьмем. ... есть этоobj
парень, так что давайте спросим его.
"Мистер obj
, у вас есть итератор?" (... звонки iter(obj)
, которые звонки
obj.__iter__()
, которые радостно раздают блестящий новый итератор _i
.)
Хорошо, это было легко ... Давайте начнем итерацию тогда. ( x = _i.next()
...x = _i.next()
...)
С мистером obj
успешно прошел этот тест (имея определенный метод, возвращающий действительный итератор), мы награждаем его прилагательным: теперь вы можете называть его «итеративный Mr. obj
».
Тем не менее, в простых случаях вам не выгодно иметь итератор и итерацию отдельно. Таким образом, вы определяете только один объект, который также является его собственным итератором. (Python на самом деле не волнует, что _i
раздают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()
Однако существуют случаи, когда вы можете извлечь выгоду из отделения итератора от итерируемого, например, когда вы хотите иметь один ряд элементов, но больше «курсоров». Например, когда вы хотите работать с «текущими» и «предстоящими» элементами, вы можете иметь отдельные итераторы для обоих. Или несколько потоков, извлекаемых из огромного списка: у каждого может быть свой собственный итератор для обхода всех элементов. Смотрите ответы @ Raymond's и @ 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__()
. Да, так и должно быть.
Вы также можете думать об этом так: итерируемый имеет данные, итератор вытягивает следующий элемент
Отказ от ответственности: я не являюсь разработчиком интерпретатора Python, поэтому я не знаю, что «думает» интерпретатор. Вышеприведенные размышления являются лишь демонстрацией того, как я понимаю эту тему из других объяснений, экспериментов и реального опыта новичка в Python.
collections.abc.AsyncIterator
тесты__aiter__
и__anext__
методы. Это новое дополнение в 3.6.