Когда я должен использовать функцию iter? - PullRequest
2 голосов
/ 14 февраля 2020

Этот код

for i in range(100, -1, -1):
   print(i)

То же, что и:

for i in iter(range(100, -1, -1)):
   print(i)

Какие номера печатаются из списка чисел 0 .. 100 в порядке убывания.

I знать об атрибуте sentinel, который останавливается при его достижении, но кроме того, когда я должен рассмотреть возможность использования функции iter()?

Спасибо.

Ответы [ 3 ]

4 голосов
/ 14 февраля 2020

Вот пример. Скажем, у меня есть список элементов, за которым за количеством элементов следует это количество элементов, снова и снова.

[1, 'some data', 3, 'some data', 'some data', 'some data', 2, ...]

Я хотел бы перебрать эти данные, используя вложенные циклы for: внешний l oop получает количество элементов, а внутреннее l oop получает следующие n элементы списка. Два цикла могут совместно использовать явный итератор:

from itertools import islice

my_data = [1, "a", 3, "b", "c", "d", 2, "e", "f"]
my_iter = iter(my_data)
for i, count in enumerate(my_iter):
    print(f"Round {i}")
    for item in islice(my_iter, count):
        print(f'  {item}')

Этот код производит вывод

Round 0
  a
Round 1
  b
  c
  d
Round 2
  e
  f
2 голосов
/ 14 февраля 2020

Не для этого. iter() хорош для того, чтобы превратить вещи, которые будут *1003* итераторами, жаждущими память, в генераторы, или для того, чтобы превратить уже существующие итераторы в объекты, которые вы можете вызвать next() on.

Но range() уже является генератором (ну, не совсем, но он ведет себя очень похоже на единицу и имеет те же преимущества), поэтому в этом случае нет никакой пользы.

В этом отношении, для for в общем случае, если ваша итерация уже полностью существует, нет смысла делать из нее iter() - ключевое слово for уже делает это за кадром.

1 голос
/ 14 февраля 2020

В любое время, когда вам нужен итератор. Вот для чего iter, он возвращает итератор для того, что вы ему передаете. Итак, рассмотрим следующий генератор, который использует преимущества свойств итератора, а именно: он однопроходный и исчерпываемый , и извлечение итератора из итератора должно возвращать сам итератор вместо того, чтобы давать вам новый.

In [19]: import itertools

In [20]: def chunk_by_n(iterable, n):
    ...:     islice = itertools.islice
    ...:     iterator = iter(iterable)
    ...:     chunk = list(islice(iterator, n))
    ...:     while chunk:
    ...:         yield chunk
    ...:         chunk = list(islice(iterator, n))
    ...:

In [21]: iterable = range(100)

In [22]: chunks = chunk_by_n(iterable, 3)

In [23]: next(chunks)
Out[23]: [0, 1, 2]

In [24]: next(chunks)
Out[24]: [3, 4, 5]

In [25]: next(chunks)
Out[25]: [6, 7, 8]

Теперь посмотрите, что произойдет, если мы не сделаем итератор из ввода:

In [26]: def chunk_by_n(iterable, n):
    ...:     islice = itertools.islice
    ...:     #iterator = iter(iterable)
    ...:     iterator = iterable
    ...:     chunk = list(islice(iterator, n))
    ...:     while chunk:
    ...:         yield chunk
    ...:         chunk = list(islice(iterator, n))
    ...:

In [27]: chunks = chunk_by_n(iterable, 3)

In [28]: next(chunks)
Out[28]: [0, 1, 2]

In [29]: next(chunks)
Out[29]: [0, 1, 2]

In [30]: next(chunks)
Out[30]: [0, 1, 2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...