Что делает iter () для вывода списка?

У меня есть такой код:

a = ['animal', 'dog', 'car', 'bmw', 'color', 'blue']
a_iter = iter(a)

print(a)
print(a_iter)

print(dict(zip(a,a)))
print(dict(zip(a_iter,a_iter)))

и вывод:

['animal', 'dog', 'car', 'bmw', 'color', 'blue']
<list_iterator object at 0x7f2d98b756d8>
{'dog': 'dog', 'car': 'car', 'animal': 'animal', 'color': 'color', 'blue': 'blue', 'bmw': 'bmw'}
{'car': 'bmw', 'color': 'blue', 'animal': 'dog'}

Я не понимаю, почему zip работает иначе с a_iter, чем с a. Что делает iter(), список можно повторять, так зачем использовать iter()? Может ли кто-нибудь объяснить мне это хорошим примером? Я погуглил об этом, но до сих пор не понимаю.

итераторы - это особый тип объектов, они созданы для перебора, поэтому они быстрые и не сохраняются в памяти, они в основном используются в циклах for для скорости, вы всегда можете преобразовать итератор в список с помощью list() .

Jorge Rodriguez Molinuevo 02.05.2018 12:42
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
1
592
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

iter() ничего не делает со списком; объект list имеет метод __iter__, который iter() использует для создания объекта итератора. Этот объект имеет ссылку на исходный список и индекс; каждый раз, когда вы запрашиваете следующее значение в итераторе, значение текущего индекса извлекается и возвращается, а индекс увеличивается.

Вы можете использовать функцию next(), чтобы получить следующее значение от итератора:

>>> a = ['animal', 'dog', 'car', 'bmw', 'color', 'blue']
>>> a_iter = iter(a)
>>> next(a_iter)  # get the next value
'animal'
>>> next(a_iter)  # get the next value
'dog'

Обратите внимание, как повторный вызов next() дает вам новое значение. Вы можете делать это, пока итератор не будет готов:

>>> three_more = next(a_iter), next(a_iter), next(a_iter)
>>> next(a_iter)  # last one
'blue'
>>> next(a_iter)  # nothing left
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Объекты итератора списка сохраняют исходный объект списка; изменение объекта списка отразится в значениях итератора, созданных на next():

>>> b = ['foo', 'bar']
>>> b_iter = iter(b)
>>> next(b_iter)
'foo'
>>> b[1] = 'spam'
>>> b
['foo', 'spam']
>>> next(b_iter)
'spam'

zip() запрашивает следующее значение в каждом из своих аргументов, которые предполагается равными итерации; zip() называет их всех iter(). Для объектов-итераторов, таких как a_iter, iter(a_iter) возвращает сам итератор (в конце концов, это уже итератор):

>>> iter(a_iter)
<list_iterator object at 0x10e7b6a20>
>>> iter(a_iter) is a_iter
True

Поскольку a_iter будет выдавать значения из исходного списка по порядку, это означает, что вы получаете парные элементы в словаре, потому что zip() имеет две ссылки на один и тот же объект; вы фактически создаете (next(a_iter), next(a_iter)) в качестве значений шага итератора для zip(). Если вы передадите две ссылки на a, с другой стороны, zip() вызовет iter()дважды, создав два отдельных объекта-итератора, и у каждой будет свой собственный индекс для отслеживания.

Давайте рассмотрим это подробнее. Обратите внимание, что zip()также создает объект-итератор, поэтому мы можем проверить, что вызов next() на zip(), в свою очередь, заставляет a_iter сделать шаг вперед дважды:

>>> a_iter = iter(a)
>>> a_iter_zip = zip(a_iter, a_iter)
>>> a_iter_zip   # a zip object is an iterator too
<zip object at 0x10e7ba8c8>
>>> next(a_iter_zip)  # get next value of a_iter, together with the next value of a_iter
('animal', 'dog')
>>> next(a_iter)  # the a-list iterator was advanced, so now we get 'car'
'car'
>>> next(a_iter_zip)  # now a_iter is at bmw, so we get bmw and color
('bmw', 'color')

Итераторы - это независимые объекты, каждый имеет свой индекс:

>>> a_iter1 = iter(a)
>>> a_iter2 = iter(a)   # different iterator from a_iter1
>>> next(a_iter1), next(a_iter1)  # what zip() does
('animal', 'dog')
>>> next(a_iter2), next(a_iter2)  # iter2 is independent
('animal', 'dog')

Итак, когда вы используете zip(a, a), на самом деле происходит то, что zip() вызывает iter(a) два раза, создавая два новых итератора, и оба используются для создания вывода:

>>> a_iter1 = iter(a)
>>> a_iter2 = iter(a)
>>> a_iter_1_and_2_zip = zip(a_iter1, a_iter2)
>>> next(a_iter_1_and_2_zip)  # values from a_iter1 and a_iter2
('animal', 'animal')
>>> next(a_iter_1_and_2_zip)  # moving in lockstep
('dog', 'dog')
>>> next(a_iter1)   # moving one of these two one step along, to 'car'
'car'
>>> next(a_iter_1_and_2_zip)   # so a_iter1 is one step ahead!
('bmw', 'car')
>>> next(a_iter1)   # another extra step
'color'
>>> next(a_iter_1_and_2_zip)   # so a_iter1 is two steps ahead!
('blue', 'bmw')

Функция iter () возвращает экземпляр итератора, в котором мы можем выполнять итерацию для получения всех значений одно за другим. Это функция, эффективная с точки зрения памяти, поскольку она хранит только текущее значение элемента.

Ответ принят как подходящий

iter(l) возвращает объект-итератор для l. Вместе с next(i) его можно использовать для итерации элементов l.

Код:

for x in l: print(x)

эквивалентно этому коду, явно использующему итератор:

i = iter(l)
while True:
    try:
        x = next(i)
        print(x)
    except StopIteration:
        break

Обратите внимание, что итератор также можно пройти с помощью цикла for:

i = iter(l)
for x in i:
    print(x)

zip(a,b) потребляет по одному элементу из a, b за раз.

Когда аргумент zip является последовательностью, он создаст для нее свой собственный итератор.

Когда аргумент является итератором, он просто потребляет элементы из него.

Если в обоих аргументах используется итератор тоже самое, каждая итерация zip будет использовать один элемент итератора для первого аргумента и один элемент для второго аргумента.

>>> a = [1,2,3,4]
>>> b = [10,20,30,40]

>>> list(zip(a, b)) # zip two lists
[(1, 10), (2, 20), (3, 30), (4, 40)]

>>> list(zip(a, a)) # zip a list with itself
[(1, 1), (2, 2), (3, 3), (4, 4)]

>>> i1 = iter(a)
>>> i2 = iter(a)
>>> list(zip(i1, i2)) # same as above, but with iterators
[(1, 1), (2, 2), (3, 3), (4, 4)]

>>> i = iter(a)
>>> list(zip(i, i)) # same as above, but with the same iterator
[(1, 2), (3, 4)]

Спасибо за отличное объяснение!

dorinand 02.05.2018 15:00

Другие вопросы по теме