3 вопроса о генераторах и итераторах в Python - PullRequest
0 голосов
/ 09 июня 2018

Все говорят, что вы теряете преимущество генераторов, если вы помещаете результат в список.

  1. Но вам нужен список или последовательность, чтобы даже иметь генератор для начала, верно?Так, например, если мне нужно просмотреть файлы в каталоге, не нужно ли мне сначала сделать их списком, как с os.listdir ()?Если так, то как это более эффективно?(Я всегда работаю со строками и файлами, поэтому мне очень не хочется, чтобы во всех примерах использовались диапазон и целые числа, но я отвлекся)Ключевое слово yield должен сделать генератор.Итак, если я сделаю:

    for x in os.listdir():
        yield x
    

Список все еще создается?Или теперь os.listdir () сам по себе также является генератором?Возможно ли, что os.listdir () еще не был вызван, что на самом деле еще нет списка здесь?

Наконец, нам говорят, что итераторам нужны методы iter () и next ().Но не значит ли это, что им нужен индекс?Если нет, то на что работает next ()?Как он узнает, что будет дальше без индекса?До 3.6 у ключей dict не было порядка, так как же работала эта итерация?

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

1) Это неправильно;это просто самый простой пример для объяснения генератора из списка.Если вы думаете о проблеме 8 ферзей и возвращаете каждую позицию, как только программа ее находит, я нигде не могу распознать список результатов.Обратите внимание, что часто итераторы поочередно предлагаются даже стандартной библиотекой Python (islice() против slice()), и простой пример, не представляемый списком, - itertools.cycle().

. В результате 2 и 3 такженеправильно.

0 голосов
/ 09 июня 2018
  1. Нет.

Смотрите, здесь нет списка:

def one():
    while True:
        yield 1
Index и next() - два независимых инструмента для выполнения итерации.Опять же, если у вас есть объект такой, что его итератор next() всегда возвращает 1, вам не нужны никакие индексы.

Более подробно ...

Смотрите, технически, вы всегда можете связать список и индекс с любым генератором или итератором: просто запишите все его возвращаемые значения - вы получите не более чем счетный набор значений a₀, a₁, ... Но это всего лишь математический формализм совершенно излишнеиметь что-то общее с тем, как работает настоящий генератор.Например, у вас есть генератор, который всегда дает один.Вы можете посчитать, сколько из них вы уже получили, и назвать это индексом.Вы можете записать все эти, разделенные запятыми, и назвать это списком.Правильно ли описывают эти два объекта выход вашего истекшего генератора?Видимо так.Они хоть немного важны для самого генератора?Не совсем.

Конечно, реальный генератор, вероятно, будет иметь состояние (вы можете назвать его индексом - при условии, что вы не обязательно называете что-то индексом, если это только неотрицательный интегральный скаляр; выможет записывать все свои состояния при условии, что он работает детерминистически, нумерует их и вызывает индекс номера текущего состояния - да, примерно так).У них всегда будет источник их состояний и возвращаемых значений.Таким образом, индексы и списки можно рассматривать как абстракции , которые описывают поведение объекта.Но совершенно необязательно, что это конкретные детали реализации, которые действительно используются.

Рассмотрим небуферизованную программу чтения файлов.Он извлекает с диска один байт и немедленно возвращает его.В памяти нет реального списка, только содержимое файла на диске (может даже и не быть, если наше устройство чтения файлов подключено к сетевому сокету вместо реального дисковода, а Oracle Delphi находится на другом конце соединения),Вы можете вызывать индекс положения файла - пока вы не прочитаете стандартный ввод, который является только обращаемым вперед и, таким образом, индексирование не имеет реального физического смысла - то же самое касается сетевых подключений по ненадежному протоколу, BTW.

Примерно так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...