Генераторы Ruby против генераторов Python
Я изучал сходства/различия между генераторами Ruby и Python (известный как Enumerators
в Ruby), и насколько я могу сказать, они в значительной степени эквивалентны.
Однако одно замечание, которое я заметил, это то, что генераторы Python поддерживают метод close()
, тогда как Ruby Generators этого не делают. Из документов Python метод close()
, как говорят, выполняет следующие действия:
Вызывает генератор Exit в точке, где функция генератора была приостановлена. Если функция генератора затем вызывает StopIteration (путем выхода из нормального состояния или из-за уже закрытого состояния) или GeneratorExit (если не поймать исключение), close возвращает его вызывающему.
Есть ли веская причина, почему Ruby Enumerators
не поддерживает метод close()
? Или это случайный
упущение?
Я также обнаружил, что Ruby Enumerators
поддерживает метод rewind()
, но генераторы Python не... есть ли причина для этого тоже?
Спасибо
Ответы
Ответ 1
Эта документация для метода перемотки немного редка. Но для того, чтобы "начать", генератор должен был бы сделать одну из двух вещей:
- запомнить его полный вывод, повторить этот вывод после перемотки, затем возобновить то, что он делал до
- reset его внутреннее состояние таким образом, чтобы повторять один и тот же вывод без других нежелательных побочных эффектов.
Вторая из них не всегда возможна; например, если генератор испускает байт-буферы из сети, выход не является полностью функцией внутреннего состояния. Но любой генератор, который использует первый метод, должен обязательно создавать большой и больший буфер в памяти, поскольку он используется. Такие генераторы предлагают небольшое преимущество в производительности по спискам.
Поэтому я заключаю, что метод Ruby rewind
должен быть необязательным и не всегда поддерживаться конкретным классом перечислителя. Поэтому, если дизайнеры Python оценивают принцип замены Лискова, это приведет к тому, что они не потребуют такого метода во всех генераторах.
Ответ 2
Генераторы основаны на стеках, Ruby Enumerators часто специализируются (на уровне интерпретатора), а не на основе стека.
Ответ 3
Ruby Enumerator использует класс StopIteration внутри, см. Как работают Enumerators в Ruby 1.9.1?
(он просто завернут, если вы используете его в для каждого вызова). Поэтому я бы сказал, что они довольно близки. Это, как говорится, я не уверен, что должен делать закрытый метод для перечислителя, точно... очистка, возможно? (Генераторы Python, вероятно, извлекли бы выгоду из перемотки - хорошо заметьте, что в Ruby некоторые счетчики не реагируют на перемотку, поэтому они вызывают исключение, когда вы вызываете этот метод).