Ruby генераторы против генераторов Python - PullRequest
20 голосов
/ 25 сентября 2010

Я исследовал сходства / различия между генераторами Ruby и Python (в Ruby они известны как Enumerators), и, насколько я могу судить, они в значительной степени эквивалентны.

Однако я заметил одно отличие в том, что Python Generators поддерживают метод close(), тогда как Ruby Generators нет. Говорят, что из документации по Python метод close() делает следующее:

Поднимает GeneratorExit в точке, где функция генератора была приостановлена. Если функция генератора затем вызывает StopIteration (путем обычного выхода или из-за того, что оно уже закрыто) или GeneratorExit (не перехватывая исключение), close возвращает его вызывающему. "

Есть ли веская причина, по которой Ruby Enumerators не поддерживает метод close()? Или это случайный упущение?

Я также обнаружил, что Ruby Enumerators поддерживает метод rewind(), но генераторы Python не ... есть ли причина для этого тоже?

Спасибо

Ответы [ 3 ]

7 голосов
/ 28 июня 2012

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

  • запомните его полный вывод, повторите этот вывод после перемотки, затем возобновите то, что он делал до
  • сбрасывает свое внутреннее состояние таким образом, что тот же вывод повторяется без других нежелательных побочных эффектов

Второе из них не всегда возможно; например, если генератор испускает байтовые буферы из сети, выходные данные не полностью зависят от внутреннего состояния. Но любой генератор, который использует первую технику, должен обязательно создавать больший и больший буфер в памяти, как он используется. Такие генераторы предлагают небольшое преимущество в производительности по сравнению со списками.

Поэтому я заключаю, что метод Ruby rewind должен быть необязательным и не всегда поддерживаться конкретным классом перечислителя. Так что, если разработчики Python оценят принцип подстановки Лискова , это приведет к тому, что им не потребуется такой метод во всех генераторах.

2 голосов
/ 26 сентября 2010

Генераторы основаны на стеке, перечислители Ruby часто специализированы (на уровне интерпретатора) и не основаны на стеке.

1 голос
/ 29 сентября 2010

Ruby's Enumerator использует внутренний класс StopIteration, см. Как работают перечислители в Ruby 1.9.1?

(он просто переносится, если вы используете его для каждого вызова).Так что я бы сказал, что они довольно близко.При этом, я не уверен, что метод close на перечислителе должен делать, точно ... очистить, возможно?(Генераторы Python, вероятно, выиграют от перемотки - обратите внимание, что в Ruby некоторые перечислители не отвечают на перемотку, поэтому они вызывают исключение при вызове этого метода).

...