Наведені вище відповіді чудові, але, як і більшість того, що я бачив, не підкреслюйте різницю достатньо для таких людей, як я.
Крім того, люди схильні отримувати "занадто піфонічний", ставлячи раніше визначення "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.