Наведені вище відповіді чудові, але, як і більшість того, що я бачив, не підкреслюйте різницю достатньо для таких людей, як я.
Крім того, люди схильні отримувати "занадто піфонічний", ставлячи раніше визначення "X - це об'єкт, у якого є __foo__()
метод". Такі визначення є правильними - вони базуються на філософії типізації качок, але фокус на методах має тенденцію розбиратися, намагаючись зрозуміти поняття в його простоті.
Тому я додаю свою версію.
Природною мовою,
- ітерація - це процес прийому одного елемента по черзі елементів.
У Python,
iterable - це об’єкт, який, ну, ітерабельний, що, просто кажучи, означає, що його можна використовувати в ітерації, наприклад, з 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 та @ 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.