Подтвердить что ты не робот

Как обращаться с исчерпанным итератором?

При поиске Python Documentation я нашел эквивалентную реализацию Python для создания Pythons zip() функция.

Вместо того, чтобы ловить StopIteration исключение, которое сигнализирует о том, что больше нет элементов, созданных итератором , автор ) используйте оператор if, чтобы проверить, была ли принятая форма значения по умолчанию next() равна object() ( "sentinel" ) и остановите генератор:

def zip(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    sentinel = object()
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            elem = next(it, sentinel)

            if elem is sentinel:
                return

            result.append(elem)
        yield tuple(result)

Интересно, существует ли какая-либо разница между приложением исключения или выражением if, используемым документами Python?

Или лучше, поскольку главный герой @hiro указал:
Что не так с использованием оператора try, учитывая EAFP (проще просить прощения, чем разрешение) в Python?

def zip(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:

            try:
                elem = next(it)
            except StopIteration:
                return

            result.append(elem)
        yield tuple(result)

Также как Стоян Деков сказал: "Блок try/except чрезвычайно эффективен , если исключения не подняты. Фактически ловить исключение дорого". (см. документы для получения дополнительной информации)
Но исключение произойдет только один раз, а именно, как только итератор исчерпан. Таким образом, обработка исключений будет лучшим решением в этом случае?

4b9b3361

Ответ 1

Вы имеете в виду, в отличие от этого?

def zip2(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            try:
                elem = next(it)
            except StopIteration:
                return

            result.append(elem)
        yield tuple(result)

Интересный вопрос... я бы предпочел эту альтернативную версию, особенно учитывая EAFP (проще попросить прощения, чем разрешение.)

даже если try/except медленнее, чем оператор if; это происходит только один раз - как только первый итератор исчерпан.

возможно, стоит отметить, что это не фактическая реализация в python; просто реализация, эквивалентная реальной реализации.


ОБНОВЛЕНИЕ в соответствии с комментариями:

обратите внимание, что PEP 479 предлагает return из генератора и не поднимать StopIteration.

Ответ 2

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

Из Документы Python.

Блок try/except чрезвычайно эффективен, если не возникает никаких исключений. На самом деле ловить исключение дорого.

Оба варианта использования if/else и try/catch имеют свои преимущества и недостатки в зависимости от ситуации.

  • Например, try/catch используется в основном для случаев, когда исключение является редким событием (например, код будет почти во всех случаях).
  • В вашем примере вы знаете, что цикл будет генерировать исключение каждый раз, когда он вызывается, что делает очень неэффективным использование try/catch

Ответ 3

Когда вы видите эквивалентный код python в документах, цель такого кода легко понять. if легко понять, а try/except - конструкция более высокого уровня.

Функционально нет разницы. Разумеется, может быть небольшая, но, вероятно, незначительная разница.

Что касается реального кодирования, разные люди думают по-разному, поэтому используйте тот способ, который имеет для вас больше смысла. Время, когда LBYL и EAFP действительно имеют значение, - это когда условие гонки может существовать - и здесь нет такого условия.