возвращаясь из цикла - PullRequest
8 голосов
/ 02 марта 2010

Я довольно новичок в Python, и мне было интересно, если это:

def func(self, foo):
    for foo in self.list:
        if foo.boolfunc(): return True
    return False

- хорошая практика.

Могу ли я вернуться из цикла, как описано выше, или я должен использовать цикл while, как это?

def func(self, foo):  
    found = false
    while(not found & i < len(self.list)):
        found = foo.boolfunc()
        ++i
    return found

Мой преподаватель Java предупреждает нас, чтобы мы никогда не использовали разрывы в наших циклах, но технически это не разрыв, и он более лаконичен, так что ... да

спасибо

Ответы [ 6 ]

14 голосов
/ 02 марта 2010

В вашем примере нет ничего плохого, но лучше написать

def func(self, foo):
    return any(foo.boolfunc() for foo in self.list)
8 голосов
/ 02 марта 2010

Следует отметить, что в Python для циклов может иметь условие else . Предложение else выполняется только тогда, когда цикл завершается из-за исчерпания списка.

Чтобы вы могли написать:

def func(self):
    for foo in self.list:
        if foo.boolfunc():
            return True
    else:
        return False
6 голосов
/ 02 марта 2010

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

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

5 голосов
/ 02 марта 2010

«Ранний выход» - это совершенно Pythonic стиль (если это оправдано: ответ gnibbler правильно указывает на то, что для вашего конкретного случая есть встроенный [[в Python 2.5 и выше]], который предпочтительнее) и часто помогает реализовать Pythonic цель "квартира лучше вложенной". И for, как правило, является правильным способом сделать цикл в Python на уровне приложения: если есть какая-либо сложная логика цикла (что может потребовать while), часто лучше в любом случае передать ее вспомогательному генератору.

Преимущества, иногда заявляемые для альтернативной «единой точки выхода», включают в себя наличие единого «узкого места выхода», при котором может быть выполнена очистка. Но так как исключения всегда возможны, вы не знаете , что ваш единственный return является уникальным узким местом выхода, даже если он у вас есть: вместо этого * 1008 - это правильный способ обеспечить хорошую очистку * оператор (в 2.6 или 2.5 с «импортом из будущего»; для более старых версий Python более грубый, но все же полезный try / finally вместо этого).

Статья Кнута «Структурированное программирование с утверждениями Гото» (pdf) - невероятная, призрачная статья 1974 года, написанная человеком, которого многие считают живой легендой информатики, теоретической и практической, - стоит прочитать. Любой, кто сомневается в применимости статьи к Python, должен рассмотреть следующую короткую цитату из нее:

устройства, такие как отступ, а не разделители, может стать возможным для выражая местную структуру в исходный язык.

за двадцать лет до публикации Python 1.0, Кнут уже предвидел ключевой синтаксический аспект, который должен был стать таким признаком Python (и, независимо, Haskell , выпущенный немного раньше, чем Python - из личной беседы с Кнутом, Пейтоном Джонсом и ван Россумом, я могу засвидетельствовать, что все они утверждают, что эти три изобретения «отступа для группировки» были полностью независимы друг от друга, только случай «великие умы думают одинаково» - или, по словам Чарльза Форта, «это было просто время парового двигателя»; -).

Формальные доказательства кода, включая ранний выход, конечно, не намного сложнее, чем эквивалентный код с одной точкой выхода, если не что иное, потому что знаменитое доказательство Коррадо Бёма и Джузеппе Якопини показывает, как выполнить механическое преобразование из любой блок-схемы к той, которая содержит только последовательность, выбор и повторение (но, конечно, преобразованная программа - как и любая другая программа, пытающаяся избежать стиля раннего выхода) - склонна иметь больше вложенности, чем необходимо, и дополнительную логическую переменную «status», которые мешают удобочитаемости, прямоте и эффективности - делают ранний выход намного лучше в тех языках, которые его хорошо поддерживают).

2 голосов
/ 02 марта 2010

Это хорошая практика.

Мой java-профессор предупреждает нас никогда не использовать разрывы в наших циклах

Почему это? «Никогда» - сильное слово в информатике, и его никогда нельзя (…) использовать. 1)


1) За исключением "goto" ... у всех нас есть наши любимые мозоли. ; -)

0 голосов
/ 02 марта 2010

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

Если ваше if утверждение имеет умеренную сложность, тогда может стать неясно, какое постусловие устанавливает цикл.

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

Если ваше условие выхода не очевидно , то запутанный, вложенный, сложный для восприятия набор if приносит вам больше вреда, чем пользы.

Действительно, этот вопрос SO показывает, что наличие простого try блока может привести к таким ситуациям, которые приводят в замешательство, так что явно некорректный фрагмент кода был создан и не может быть легко отлажен.

Как правило, все вещи с «ранним выходом» (в частности, оператор break) приводят к проблемам, создающим формальное доказательство. (У оператора else есть похожие проблемы.)

Если вы разрабатываете свою программу, аргументируя операторы, необходимые для создания необходимого пост-условия, вам никогда не понадобится break или ранний return, потому что вы не можете легко создать эти операторы с помощью формальных методов.

Также обратите внимание, что любые советы, которые следует избегать break или else, приведут к ненависти к почте и снижению голосов. По необъяснимым причинам, внимательно присматриваться к некоторым программным конструкциям - это плохо.

"еще" считается вредным в Python?

Если условие выхода из цикла с break (или ранним return) не является очевидным , вам нужно переработать вещи, чтобы сделать его очевидным .

В этом примере они очевидны , так что нет проблем с конкретным примером, как он представлен.

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