Подтвердить что ты не робот

Смутно с списками python: они или не являются итераторами?

Я изучаю Alex Marteli Python в двух словах, и книга предполагает, что любой объект, который имеет метод next(), (или, по крайней мере, может быть использован как) итератор. Он также предполагает, что большинство итераторов построены неявными или явными вызовами метода под названием iter.

Прочитав это в книге, я почувствовал желание попробовать. Я запустил интерпретатор python 2.7.3 и сделал следующее:

>>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for number in range(0, 10):
...     print x.next()

Однако результат был следующим:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
AttributeError: 'list' object has no attribute 'next'

В замешательстве я попытался изучить структуру объекта x через dir(x), и я заметил, что он имеет объект функции __iter__. Поэтому я понял, что он может использоваться как итератор, если он поддерживает этот тип интерфейса.

Итак, когда я попробовал еще раз, на этот раз несколько иначе, пытаясь сделать это:

>>> _temp_iter = next(x)

Я получил эту ошибку:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator

Но как список NOT может быть итератором, поскольку он, кажется, поддерживает этот интерфейс и может быть определенно использован как один в следующем контексте:

>>> for number in x:
...     print x

Может ли кто-нибудь помочь мне прояснить это в моем сознании?

4b9b3361

Ответ 1

Они повторяемы, но они не являются итераторами. Они могут быть переданы в iter(), чтобы получить итератор для них либо неявно (например, через for), либо явно, но они сами не являются итераторами.

Ответ 2

Вам нужно сначала преобразовать список в итератор, используя iter():

In [7]: x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [8]: it=iter(x)

In [9]: for i in range(10):
    it.next()
   ....:     
   ....:     
Out[10]: 0
Out[10]: 1
Out[10]: 2
Out[10]: 3
Out[10]: 4
Out[10]: 5
Out[10]: 6
Out[10]: 7
Out[10]: 8
Out[10]: 9

In [12]: 'next' in dir(it)
Out[12]: True

In [13]: 'next' in dir(x)
Out[13]: False

проверка, является ли объект итератором или нет:

In [17]: isinstance(x,collections.Iterator)
Out[17]: False

In [18]: isinstance(x,collections.Iterable)
Out[18]: True

In [19]: isinstance(it,collections.Iterable) 
Out[19]: True

In [20]: isinstance(it,collections.Iterator)
Out[20]: True

Ответ 3

На всякий случай вы сбиты с толку о том, какая разница между итерами и итераторами. Итератор представляет собой объект, представляющий поток данных. Он реализует протокол итератора:

  • __iter__ метод
  • next метод

Повторные вызовы итераторы next() возвращают последовательные элементы в потоке. когда больше нет данных, объект итератора исчерпан, и любые дальнейшие обращения к его next() просто снова вызовет StopIteration.

С другой стороны, итеративные объекты реализуют метод __iter__, который при вызове возвращает итератор, который допускает многократные проходы над их данными. Итерируемые объекты многоразовые, после исчерпания их можно повторить снова. Они могут быть преобразованы в итераторы с помощью функции iter.

Итак, если у вас есть список (iterable), вы можете сделать:

>>> l = [1,2,3,4]
>>> for i in l:
...     print i,
1 2 3 4
>>> for i in l:
...     print i,
 1 2 3 4

Если вы преобразуете свой список в итератор:

>>> il = l.__iter__()  # equivalent to iter(l)
>>> for i in il:
...     print i,
 1 2 3 4
>>> for i in il:
...     print i,
>>> 

Ответ 4

Список не является итератором, но в списке содержится объект-итератор __iter__, поэтому, когда вы пытаетесь использовать для цикла в любом списке, для вызова циклов метод __iter__ и получает объект итератора, а затем он использует метод next() списка.

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
it = x.__iter__()

Теперь it содержит объект итератора x, который вы можете использовать как it.next() до тех пор, пока не будет исключено исключение StopIteration