Что значит «потреблять» в Python?В итераторе? - PullRequest
12 голосов
/ 04 марта 2011

Я работаю в Python уже несколько месяцев, и мне пришло в голову, что я часто пропускаю словарный запас, который ускользает от меня на первый взгляд, вместо этого пытаясь понять суть идеи. Теперь, оглядываясь назад, я все еще не могу понять, что означает термин потребление . Мой первоначальный интерес исходил из объяснений итераторов, которые говорили о значении потребляемого итератора. Однако, оглядываясь вокруг, это не кажется обычным в лексиконе Python. Либо это? Копаясь здесь, вы найдете в основном ссылки на веб-службы и одно или два обсуждения того, как скрыть тот или иной результат функции.

Тогда, я полагаю, разбейте мое невежество на несколько базовых пунктов:

  1. Делает ли "потребляющий" разные вещи в разных контекстах Pythonic?
  2. Что происходит с данными при их использовании, например, в iter()?
  3. Когда переменная присваивается результату итератора - предположительно потребляемой части данных - она ​​больше не принадлежит итератору?
  4. Можете ли вы использовать более одного значения из объекта итератора за один вызов итератора?

Надеюсь, это имеет какой-то смысл. Обратите внимание, что это не относится к какой-либо конкретной необходимости; Я просто запутался за пределами разумного правдоподобия.

РЕДАКТИРОВАТЬ: еще одна вещь ... итеративное значение (при вызове с next()) остается в памяти?

Ответы [ 6 ]

6 голосов
/ 04 марта 2011

Термин «потреблять» - это неформальный термин, который относится к тому, как итераторы работают в Python.«Итератор» - это отдельный объект, который отвечает за создание некоторой последовательности элементов.Эта последовательность может быть элементами существующего списка, или это может быть что-то вычисленное, например, простые числа или десятичные цифры π.

Когда вызывающая сторона запрашивает «следующий» элемент у итератора, итератор предоставляетследующий элемент, а затем меняет свое собственное состояние, так что он готов производить следующий элемент после этого.Обычно это то, что вы ожидаете.

Если у меня есть генератор, который производит последовательность возрастающих простых чисел, при первом вызове я получу 2 взамен.В следующий раз я получу 3. Если я дам вам ссылку на этот генератор, вы назовете его (как вы думаете, в первый раз) и получите 5. Нет никакого способа «перезагрузить»генератор, так что он снова начнется с 2, за исключением создания совершенно нового экземпляра генератора.В этой ситуации я мог бы сказать, что я уже потребил первых двух предметов, прежде чем дать вам генератор.

4 голосов
/ 04 марта 2011

Относительно 2.

На самом деле мы должны различать два случая.

Помните, что писал Грег Хьюгилл:

«Итератор» - это один объект, который отвечает для создания некоторой последовательности элементов. Эта последовательность может быть элементами существующего списка, или это может быть что-то рассчитано, как простые числа или десятичные цифры π.

Первый случай :

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

Второй корпус

- это когда итератор возвращает ранее существующие объекты, принадлежащие списку, кортежу, словарю и т. Д. В этом случае каждый объект, созданный next(), уже имеет привязку с именем. Затем, если объекту присваивается новое имя, когда он «выскакивает» из итератора, к объекту будут привязаны два имени. И если объекту не присвоено имя, он будет по-прежнему привязываться только к одному имени, чего достаточно для поддержания объекта в живых.

Общее:

Каждый раз, когда объект создается по вызову итератора, если ему не назначено имя, единственным результатом операции является то, что итератор "использовался". Это способ сказать, что даже если после создания объекта нет постоянных последствий, оно произошло, что пропустило след внутри итератора.

Говорят о потреблении итератора, когда объекту присваивается имя, однако я не хочу путать.

Примечание:

На самом деле, в случае, если объект уже существует в списке, скажем, возможно, у него нет имени. Но список содержит ссылку на каждый объект, который он «содержит» ... На самом деле, список не «содержит» объекты, а только ссылки на объекты ... Это выходит за рамки того, что я хотел сказать.

.

Относительно 3

Вы не должны писать 3: "Когда переменной назначается ..."

Слово variable является ловушкой в ​​Python, поскольку оно имеет неоднозначное значение. В Python нет переменных , в общем смысле, известном в других языках, то есть «разделенная часть памяти, значение которой может измениться». Есть только объекты. Слово переменная обычно используется для обозначения идентификатора . Поэтому лучше называть это идентификатор или имя . Это позволяет избежать путаницы.

.

Относительно 4

Я не думаю, что можно получить два возврата от итератора только одним вызовом next()

4 голосов
/ 04 марта 2011

Я не эксперт по Python, но я могу сказать следующее: в большинстве случаев потребление в программировании противоположно производству.Вы можете классифицировать некоторые процессы как производителей, которые создают ценности;и другие как потребители, которые используют значения, созданные производителями.

В случае итератора, итератор - это производитель, который проходит через итерируемый объект и «производит» каждое значение, по одному за раз,с целью.«Потреблять» данные из итератора просто значит использовать их.

1 голос
/ 04 марта 2011

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

Имея это в виду, вызов iterator.next() можно назвать "потреблением значения", потому что в общем случае вызов next изменяет состояние итератора, и нет никакого способа вернуться к этому предыдущему. государство.

Однако ничто не мешает итератору многократно возвращать одно и то же значение или даже обеспечивает способ отката к предыдущему состоянию. В этих случаях использование слова «потреблять» может быть неприменимо.

Что касается данных, возвращаемых методом итератора next, то он полностью зависит от реализации итератора. Генераторы склонны отбрасывать результаты, которые они дают, но если контейнер также является итератором, то данные, возвращаемые при вызове next(), все еще будут существовать в объекте контейнера.

0 голосов
/ 25 марта 2016

Делает ли "потребление" разные вещи в разных контекстах Pythonic?

Нет, «потребляющий» всегда делает одно и то же.

Что происходит с данными при их использовании, например, в iter ()?

Он больше не доступен в том месте, где вы его получили.

Когда переменная присваивается результату итератора - предположительно потребляемой части данных - она ​​больше не принадлежит итератору?

Правильно. Как только итератор создает данные, данные больше не принадлежат итератору.

Можно ли использовать более одного значения из объекта итератора за один вызов итератора?

Обычно нет. Однако вы можете написать пользовательский итератор, который выдает более одного значения за раз.

0 голосов
/ 04 марта 2011

Я могу ответить на ваше первое замечание: потреблять - это исчерпывать итеративное, это означает запуск итерируемого из следующих элементов.

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