Перейти к содержимому

Как выйти из всех циклов в python

  • автор:

Выход из нескольких циклов

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

some_text = ['some text','another text','one more'] whitelist = ['another','more'] blacklist = ['some','else'] for text in some_text: for items in blacklist: if text.find(items) != -1: for item in whitelist: if text.find(item) == -1: print('Found!') else: print('Not found') 

Также прошу простить за возможные ошибки или опечатки в коде.
Отслеживать
23.4k 3 3 золотых знака 49 49 серебряных знаков 70 70 бронзовых знаков
задан 29 июн 2015 в 14:57
83 1 1 золотой знак 1 1 серебряный знак 4 4 бронзовых знака
связанный вопрос Можно ли прервать цикл, находясь внутри функции?
17 дек 2017 в 16:33

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Вариант первый, некрасивый

Для выхода из цикла до его нормального завершения в Python используется оператор break :

for item in items: if some_condition: break 

Для того, чтобы выйти из нескольких циклов по условию, выполнившемуся во внутреннем цикле, используется флаг выхода — переменная, которая изначально имеет значение False , а при необходимости выйти из цикла преждевременно принимает значение True :

flag = False for outer in outer_list: for inner in inner_list: if some_condition: flag = True break if flag: break 

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

Вариант второй, красивый

Вам стоит немного поменять структуру вашего кода. Для начала вынесите проверки на вхожденения слов из blacklist и whitelist в отдельную функцию:

def contains_words(text, words_list): for word in words_list: if text.find(word) != -1: return True return False 

Теперь проверка на вхождение слов из whitelist и невхождение слов из blacklist будет выглядеть так:

for text in some_text: if contains_words(text, whitelist) and not contains_words(text, blacklist): print("Found") else: print("Not found") 

Если выражение contains_words(text, whitelist) вернёт False , Python не станет вычислять значение выражения not contains_words(text, blacklist) , так как, каким бы оно ни было, значение выражения contains_words(text, whitelist) and not contains_words(text_blacklist) всегда будет False .

Переписав код таким образом вы сохраните изначально задуманную функциональность, при этом значительно повысив читаемость кода и упростив возможные изменения в будущем.

Как сделать «двойной break», то есть выйти из вложенного цикла, в Python?

Обложка поста Как сделать «двойной break», то есть выйти из вложенного цикла, в Python?

Если бы мы программировали, например, на Java, то мы могли бы воспользоваться механизмом меток:

outterLoop: for(int i=0; i 

Однако в Python такого механизма нет. Требуется предложить наиболее удобное в использовании и читаемое решение.

Возможные варианты ответа
  • Поместить цикл в тело функции, а затем сделать return из неё:def func():ts=»teste»tfor i in range(len(s)):ttfor j in range(i+1, len(s)):tttif s[i]==s[j]:ttttprint(i,j)ttttreturnfunc()Почему это плохая идея: разумеется, сама задача в условии — лишь абстрактный пример. В жизни циклов может быть гораздо больше, и создавать по функции для каждого из них как-то неестественно, не так ли?
  • Выбросить исключение и поймать его снаружи цикла:try:ts=»teste»tfor i in range(len(s)):ttfor j in range(i+1, len(s)):tttif s[i]==s[j]:ttttprint(i,j)ttttraise Exception()except:tprint(«the end»)Почему это плохая идея: здесь мы используем механизм исключений как особую форму goto, но ведь на самом деле ничего исключительного в коде не произошло — это обычная ситуация. Как минимум, причины такого злоупотребления этим механизмом будут непонятны другим программистам.
  • Можно создать булевую переменную, которая будет хранить информацию о том, нужно ли выходить из внешнего цикла на данной итерации:exitFlag=Falses=»teste»for i in range(len(s)):tfor j in range(i+1, len(s)):ttif s[i]==s[j]:tttprint(i,j)tttexitFlag=Truetttbreaktif(exitFlag):ttbreakПочему это плохая идея: из всех перечисленных выше идей эта, пожалуй, лучшая. Тем не менее, это весьма низкоуровневый подход, и в языке Python есть возможность реализовать задуманное гораздо лучше.
  • Использовать вместо двух циклов for один while :s=»teste»i=0j=1while i < len(s):tif s[i] == s[j]:ttprint(i, j)ttbreaktj=j+1ti=i+j//len(s)tj=j%len(s)Почему это плохая идея: вам не кажется, что такой код читается хуже всех предложенных вариантов?
Решение на пятёрку

Давайте ещё раз внимательно прочитаем условие:

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

Где там вообще хоть слово про двойной цикл или про перебор двух индексов? Нам нужно перебирать пары. Значит, по идее, мы должны написать что-то вроде этого:

s = "teste" for i, j in unique_pairs(len(s)): if s[i] == s[j]: print(i, j) break 

Отлично, так мы будем перебирать пары. Но как нам добиться именно такой формы записи? Всё очень просто, нужно создать генератор. Делается это следующим образом:

def unique_pairs(n): for i in range(n): for j in range(i+1, n): yield i, j 

“Как это работает?” — спросите вы. Всё просто. При вызове unique_pairs(int) код в теле функции не вычисляется. Вместо этого будет возвращён объект генератора. Каждый вызов метода next() этого генератора (что неявно происходит при каждой итерации цикла for ) код в его теле будет выполняться до тех пор, пока не будет встречено ключевое слово yield . После чего выполнение будет приостановлено, а метод вернёт указанный объект (здесь yield действует подобно return). При следующем вызове функция начнёт выполняться не с начала, а с того места, на котором остановилась в прошлый раз. При окончании перебора будет выброшено исключение StopIteration .

Итак, самый true pythonic way в решении этой задачи:

def unique_pairs(n): for i in range(n): for j in range(i+1, n): yield i, j s = "a string to examine" for i, j in unique_pairs(len(s)): if s[i] == s[j]: print(i, j) break 

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

itertools.combinations(s, 2) 

Что же, для данной задачи это действительно более pythonic решение. Хочется отметить, что целью статьи было скорее познакомить новичков с механизмом генераторов, нежели действительно решить проблему, заявленную в первом абзаце ?

Свои варианты предлагайте в комментариях!

5 способов выйти из вложенного цикла в Python

Все мы знаем, что Python — довольно элегантный язык программирования, но, увы, у всех есть свои слабые стороны. Иногда Python выглядит не так аккуратно, как ему следовало бы. К примеру, нам нужно выйти из вложенного цикла как на примере ниже:

for a in list_a: 
for b in list_b:
if condition(a,b):
break

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

Конечно, сравнивать языки друг с другом не стоит, но вот в PHP такое действие довольно просто можно провернуть:

foreach ($a_list as $a)
foreach ($b_list as $b)
if (condition($a, $b))
break 2; //break out of 2 loops
>
>
>

В PHP ключевое слово break принимает число в качестве аргумента, которое определяет, из скольки вложенных циклов нужно выйти. Значением по умолчанию установлено 1, что как раз позволяет выйти из крайнего цикла. Это довольно лаконичное и разумное решение, PHP выглядит привлекательнее с точки зрения написания кода.

Правда, это не значит, что всем пора бежать изучать PHP. Python все-таки очень гибкий язык, так что того же результата можно достичь многими другими способами.

В статье представлено 5 способов выхода из вложенного цикла в Python. В конце статьи также указано, как можно избежать проблемы вложенности в циклах.

1. Переменная-флаг

Первое решение довольно простое и эффективное. Чтобы выйти из цикла, надо объявить переменную и использовать ее как flag . Рассмотрим решение на примере ниже:

# добавьте переменную-флаг
break_out_flag = False
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
break_out_flag = True
break
if break_out_flag:
break

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

2. Вызов исключения

Если мы не можем использовать ключевое слово break как положено, почему бы тогда не выразить его действие другим способом? В Python существует возможность обработки исключений, поэтому из вложенного цикла можно выйти таким образом:

# вызовите исключение
try:
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
raise StopIteration
except StopIteration:
pass

Код выше показывает, что break можно выразить как исключение и таким образом выйти из цикла.

3. Повторная проверка условия

Поскольку выполнение одного условия приводит к прерыванию цикла, проверка того же условия также кажется приемлемым решением. Вот как это выглядит:

# проверьте то же условие второй раз
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
break
if j == 2 and i == 0:
break

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

4. Конструкция for-else

В Python есть особая конструкция for-else . Она не очень популярна, а некоторые совсем о ней не знают. Обычно, если пишут else , то только после if . А вот когда дело доходит до выхода из вложенных циклов, то такой необычный синтаксис может помочь в решении задачи:

# используйте конструкцию For-Else
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
break
else: # можно вызывать, только если во внутреннем цикле нет break
continue
break

Этот метод берет все лучшее от синтаксиса for-else , так как код в блоке else сработает только в том случае, если внутренний цикл закончится без выхода. Если вы еще не знакомы с конструкцией for-else , то ознакомьтесь с кодом ниже — это конструкция, которая объясняет поведение конструкции:

# то же самое, что и конструкция for-else
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
break
if not (j == 2 and i == 0):
continue
break

Если вкратце, то этот способ работает, но требует использования необычного синтаксиса.

5. Дополнительная функция

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

# напишите для этого функцию
def check_sth():
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
return
check_sth() # запустите функцию, где нужно

Это решение выглядит более понятно, тут нет переменных-флагов, нет try-except , for-else и ненужных проверок условий. Функции в Python настраиваются очень гибко, так что если вложенный цикл будет присутствовать по одному разу в каждой функции, то можно вызвать ее сразу во внешней функции:

def out_func(): 
# какой-то код
def check_sth():
for i in range(5):
for j in range(5):
if j == 2 and i == 0:
return
# какой-то код
check_sth() # запуск функции
# какой-то код

Правда, создание вложенной функции для двух циклов тоже выглядит не особо разумно.

Cовет: избегайте вложенных циклов

Но на деле, если не существует действительно удобных решений для выхода из вложенных циклов, тогда почему бы не постараться избегать их? Применяя вспомогательную функцию, можно избежать вложенных циклов:

# как избежать вложенных циклов
import itertools
for i, j in itertools.product(range(5), range(5)):
if j == 2 and i == 0:
break

Этот пример показывает, как с помощью функции itertools.product() можно обойтись без вложенности. Это простой способ вычисления декартова произведения на основе входных итераций. К несчастью, этим методом не получится избежать любых вложенных циклов. К примеру, он не сработает, если вам необходимо будет обработать бесконечные потоки данных в циклах.

Перед тем как функция itertools.product() начнет свою работу, ей необходимо получить на вход все переменные, сохраняя в памяти массивы значений для генерации результата. Таким образом, функция полезна только при конечном количестве входных данных. И всё же лучше следовать совету не прибегать к вложенным циклам, ведь это улучшает читаемость кода.

Заключение

У нас есть как минимум 5 возможных путей выхода из вложенных циклов в Python. Ни один из них не является настолько же удобным, как в PHP, но, по крайней мере, они все же существуют. К счастью, нам не обязательно использовать вложенные циклы, так как мы можем преобразовать их в простые циклы благодаря функции itertools.product() .

  • Python для начинающих: all, any, zip, enumerate, filter, map
  • Жажда скорости: Python с расширениями С
  • Асинхронная многопоточность в Python

Использование выражений Break, Continue и Pass при работе с циклами в Python 3

Использование выражений Break, Continue и Pass при работе с циклами в Python 3

Использование циклов for и циклов while в Python помогает эффективно автоматизировать и воспроизводить задачи.

Однако иногда на работу вашей программы может влиять внешний фактор. Когда это произойдет, вы можете захотеть, чтобы ваша программа полностью вышла из цикла, пропустила часть цикла и продолжила его выполнение или игнорировала этот внешний фактор. Для этих действий используются выражения break , continue и pass .

Выражение Break

В Python выражение break дает вам возможность выйти из цикла при активации внешнего условия. Выражение break помещается в блок кода внутри выражения loop, обычно после условного выражения if .

Рассмотрим пример использования выражения break в цикле for :

number = 0 for number in range(10): if number == 5: break # break here print('Number is ' + str(number)) print('Out of loop') 

В этой небольшой программе переменная number инициализируется как 0. Затем выражение for строит цикл, пока значение переменной number составляет меньше 10.

В цикле for имеется выражение if , которое задает условие, что если значение переменной number равно целому числу 5, то цикл прекращается.

В цикле также содержится выражение print() , которое выполняется с каждой итерацией цикла for , пока цикл не прекращается, поскольку оно располагается после выражения break .

Чтобы узнавать о выходе из цикла, мы добавили завершающее выражение print() вне цикла for .

При выполнении этого кода результат будет выглядеть следующим образом:

Output
Number is 0 Number is 1 Number is 2 Number is 3 Number is 4 Out of loop

Это показывает, что когда переменная number оценивается как эквивалентная целому числу 5, цикл прекращается, поскольку программа получает соответствующее указание через выражение break .

Выражение break заставляет программу выйти из цикла.

Выражение Continue

Выражение continue дает возможность пропустить часть цикла, где активируется внешнее условие, но при этом выполнить остальную часть цикла. При этом прерывается текущая итерация цикла, но программа возвращается к началу цикла.

Выражение continue размещается в блоке кода под выражением цикла, обычно после условного выражения if .

Мы используем ту же программу с циклом for , что и в разделе «Выражение Break» выше, но при этом используем выражение continue вместо выражения break :

number = 0 for number in range(10): if number == 5: continue # continue here print('Number is ' + str(number)) print('Out of loop') 

Отличие выражения continue от выражения break заключается в том, что код продолжит выполняться несмотря на прерывание, если значение переменной number будет оценено как равное 5. Давайте посмотрим на результаты:

Output
Number is 0 Number is 1 Number is 2 Number is 3 Number is 4 Number is 6 Number is 7 Number is 8 Number is 9 Out of loop

В этом выводе условие Number is 5 никогда не выполняется, но цикл продолжается после этого, чтобы выводить линии для чисел 6–10 до выхода из цикла.

Вы можете использовать выражение continue , чтобы избежать использования глубоко вложенного условного кода или чтобы оптимизировать цикл, устранив часто встречающиеся случаи, которые вы хотите отклонять.

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

Выражение Pass

При активации внешнего условия выражение pass позволяет обрабатывать условия без влияния на цикл; чтение кода будет продолжаться до появления выражения break или другого выражения.

Как и в случае с другими выражениями, выражение pass будет содержаться в блоке кода до выражения loop, обычно после условного выражения if .

Используя тот же код выше, попробуйте заменить выражение break или continue выражением pass :

number = 0 for number in range(10): if number == 5: pass # pass here print('Number is ' + str(number)) print('Out of loop') 

Выражение pass , появляющееся после условного выражения if , указывает программе на необходимость продолжить выполнение цикла и игнорировать тот факт, что переменная number оценивается как равная 5 во время одной из итераций.

Мы запустим программу и оценим вывод:

Output
Number is 0 Number is 1 Number is 2 Number is 3 Number is 4 Number is 5 Number is 6 Number is 7 Number is 8 Number is 9 Out of loop

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

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

Заключение

Выражения break , continue и pass в Python позволяют использовать циклы for и while в вашем коде более эффективно.

Чтобы больше поработать с выражениями break и pass , вы можете выполнить учебный модуль нашего проекта «Создание бота Twitterbot с помощью Python 3 и библиотеки Tweepy».

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *