Приведенные выше ответы великолепны, но, как большинство из того, что я видел, не подчеркивайте различие , достаточное для таких людей, как я.
Кроме того, люди, как правило, получают «слишком Pythonic», помещая такие определения, как «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
успешно прошел этот тест (имея определенный метод, возвращающий действительный итератор), мы вознаграждаем его прилагательным: теперь вы можете называть его «итеративный г-н 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's ответов выше.
Представьте, что вы можете сделать:
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()
может выдать StopItered, чтобы остановить итерацию. Не должны,
тем не менее, он может повторяться вечно или использовать другие средства.
В вышеупомянутом «мыслительном процессе» _i
на самом деле не существует. Я придумал это имя.
В Python 3.x есть небольшое изменение: next()
метод (не встроенный) сейчас
должен называться __next__()
. Да, так должно было быть все время.
Вы также можете думать об этом так: итеративный имеет данные, итератор вытягивает следующий
пункт
Отказ от ответственности: Я не являюсь разработчиком какого-либо интерпретатора Python, поэтому я действительно не знаю, что "думает" интерпретатор. Приведенные выше размышления являются лишь демонстрацией того, как я понимаю эту тему из других объяснений, экспериментов и реального опыта новичка в Python.