Как сделать постоянную проверку условий в python
Перейти к содержимому

Как сделать постоянную проверку условий в python

  • автор:

Изучаем Python -> Условия

Привет-привет, DTF! В этом лонге, я продолжаю цикл статей, которые помогут Вам в изучении Python. Всё с примерами и наглядно. Читай, узнавай, подписывайся!

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

Весь код я предлагаю писать в Google Colab, для этого нам понадобиться там зарегистрироваться (подойдет учетка Google) и создать новый блокнот (Файл -> Создать блокнот).

Также, если у Вас возникли трудности, можете просмотреть мой блокнот, в нём изложен весь сегодняшний материал.

Условие — это способ описать событие, при выполнении которого, произойдёт определенный сценарий действий.

Для начала, разберемся, а какие в принципе, бывают условия

< Меньше — условие верно, если левое значение меньше правого

> Больше — условие верно, если левое значение больше правого

>= Больше или равно — условие верно, если левое значение меньше или равно правому

== Равенство. Условие верно, если два значения равны

!= Неравенство. Условие верно, если два значения неравны.

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

Мы пишем ключевое слово, говорящее Python, что сейчас начнётся запись условия. Лайфхак, если Вы слышите предложение, которое начинается со слова «если» — то перед Вами ставят условие. В английском языке если переводится как if и именно с него начинается всякое условие.

Далее следует само условие. Сравниваем что-то с чем-то, способы сравнить описаны выше. В конце условия ставится двоеточие, которое готовится описывать события, последующие после выполнения условия. Его еще можно сравнить со словом «тогда».

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

Получаем, вот такую конструкцию:

если условие верно тогда:

____описание последующих действий

Теперь, поговорим про каждое из них более подробно.

< Меньше — условие верно, если левое значение меньше правого.

Здесь стоит проверить, что было бы, если бы условие не выполнилось?

Давайте, рассмотрим это на примере следующего типа условий:

> Больше — условие верно, если левое значение больше правого

Зеленая галочка слева от if, указывает нам на то, что программа отработала, однако вывода не последовало. Почему? Потому что условие неверно и действие лежащее внутри этого условия никогда не будет выполнено.

Давайте, приведем условие в порядок и сделаем так, чтобы оно выполнилось.

На очереди новый тип условий.

>= Больше или равно — условие верно, если левое значение меньше или равно правому

Условие работает, аналогично прошлому, с той лишь оговоркой, что в случае равенства между собой чисел — условие всё равно будет выполнено. Лучше всего, это будет видно на примере двух рядом стоящих условий.

<= Меньше или равно — условие верно, если левое значение больше или равно правому

Не трудно догадаться, что меньше или равно работает аналогично знаку меньше, но с вышеуказанной ремаркой (в случае равенства чисел, условие будет выполнено).

== Равенство. Условие верно, если два значения равны

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

С точностью до наоборот, работает условие неравенства

!= Неравенство. Условие верно, если два значения неравны.

Все условия проверены и работают ровно так, как мы от них ожидаем. Но на этом моменте, внимательный ученик заметит, что я сравнивал только числа. Но будут ли эти условия работать со строкой? Будут.

Создадим переменную name и добавим пользователю возможность записать в неё свое имя. Затем напишем условие, что если содержимое переменной равняется строке, то выведется надпись — «Я знаю, как тебя зовут».

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

Тут нам поможет else или в переводе с английского — иначе. Как и if, данное слово в Python является специальным, оно указывает нам на то, что если ни одно из вышестоящих условий не сработало, то будет выполнено действие, стоящее после else.

Напишем такое условие, при котором, если пользователь ввёл ‘Pavel’ — программа ответит, что знает, как нас зовут, во всех иных случаях — что не знает.

4.1. Теория¶

При составлении алгоритма и написании программы возникают ситуации, когда часть действий необходимо выполнить при каком-либо условии или повторить (несколько раз или также при условии). В высокоуровневых языках программирования для этого предназначены специальные конструкции:

цикл — конструкция, предназначенная для организации многократного исполнения набора инструкций.

В языке Python ветвление и цикл поддерживаются операторами:

while : цикл с условием;

for : совместные циклы (циклы по коллекциям).

4.1.1. Условный оператор¶

Оператор if позволяет выполнять часть программы при наступлении определенного условия.

каждое из условий logical_expression_N по очереди проверяется на истинность; условия — выражения типа bool , например, x > 2 , a > 5 and b < 7 и т.д.;

как только истинное условие найдено, выполняется соответствующий блок suite_N , после чего осуществляется выход из всей условной конструкции (прочие варианты не проверяются и не выполняются);

если ни одно из условий не истинно («не срабатывает»), выполняется блок else (при наличии).

Для небольших условий возможно использование специального сокращенного варианта:

Пример использования условного оператора приведен в Листинге 4.1.1.

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

4.1.2. Циклы¶

4.1.2.1. Цикл с условием¶

Цикл с условием представлен в Python оператором while.

блок команд while_suite выполняется пока logical_expression истинно;

блок else необязателен, а его содержимое (блок else_suite ) выполняется только, если не было прерывания цикла .

https://amdy.su/wp-admin/options-general.php?page=ad-inserter.php#tab-8

Цикл с условием используется, когда количество итераций неизвестно, однако известно условие его окончания.

Пример использования цикла while приведен в Листинге 4.1.2.

Пример использования ключевого слова else приводится в разделе Прерывание и продолжение циклов .

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

4.1.2.2. Совместный цикл (цикл по коллекциям)¶

Совместный цикл представлен в Python циклом for.

в качестве iterable может использоваться любой итерируемый объект (список, словарь и др.);

блок команд for_suite выполняется для каждого элемента expression из iterable ; при этом внутри блока for_suite expression содержит ссылку на текущий просматриваемый элемент;

блок else необязателен; при наличии выполняется блок else_suite , если не было прерывания цикла .

Пример использования for приведен в Листинге 4.1.3.

Пример использования ключевого слова else приводится в разделе Прерывание и продолжение циклов .

4.1.2.2.1. Итераторы¶

Универсальность цикла for в виде возможности перемещения по различным коллекциям основана на использовании итераторов — специальных интерфейсных объектов, предоставляющих навигацию по другим (итерируемым) объектам.

Общая схема взаимодействия коллекции и итератора следующая:

коллекция и итератор взаимно ссылаются друг на друга через специальный метод __iter__() ;

итератор предоставляет дополнительный метод __next__() для получения следующего элемента привязанной коллекции (Рисунок 4.1.1).

_images/04_01_01.png

Рисунок 4.1.1 — Итератор и итерируемый объект 6 ¶

Итераторы, реализованные по-разному для различных классов (например, для кортежа и словаря) позволяют циклу for перемещаться по коллекциям, не заботясь о внутренней структуре объектов, а используя методы __iter__() и __next__() . Вызов __next__() завершается возбуждением исключения StopIteration , означающим, что элементов в коллекции больше нет (Листинг 4.1.4).

Итерируемые объекты также поддерживаются рядом полезных функций.

Возвращает True , если все элементы iterable в логическом контексте оцениваются как True .

Возвращает True , если хотя бы 1 элемент iterable в логическом контексте оцениваются как True .

enumerate ( iterable , start = 0 ) ¶

Возвращает итератор, где каждый элемент является парой «номер» — «значение». Номер отсчитывается от start . Обычно используется в циклах for , чтобы получить последовательность кортежей (номер, элемент) .

sorted ( iterable , key = None , reverse = False ) ¶

Возвращает отсортированный объект в виде списка для итерируемого объекта iterable .

key – функция сортировки (по умолчанию не учитывается, сортировка осуществляется поэлементно);

reverse – если равен True , сортировка осуществляется в обратном порядке.

Возвращает итератор, возвращающий элементы в обратном для исходного iterable порядке.

Пример использования нескольких функций приведен в Листинге 4.1.5.

4.1.2.2.2. Некоторые техники перемещения по коллекциям¶

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

4.1.2.3. Прерывание и продолжение циклов¶

Любая циклическая конструкция может быть немедленно прервана или продолжена (осуществлен переход к проверке условия или следующей итерации в циклах while и for соответственно).

Прерывание цикла может произойти при:

наличии команды break : приводит к выходу из цикла (только из того, внутри которого она написана);

наличии команды return : выход из функции (и из цикла, соответственно, Тема №5 );

Не зависимо от способа прерывания цикла, механизм действует одинаково — выполнение цикла прерывается, дополнительная часть цикла else не выполняется и осуществляется выход за пределы цикла.

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

Примеры прерывания и продолжения цикла приведены в Листингах 4.1.7 и 4.1.8.

# assert в Python

Инструкция assert применяется для автоматического об­наружения ошибок в программах Python. Эта инструкция сделает ваши программы надежнее и проще в отладке.

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

Пример использования assert

Предположим, вы создаете интернет-магазин с помощью Python. Вы рабо­таете над добавлением в систему функциональности скидочного купона, и в итоге вы пишете следующую функцию apply_discount() :

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

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

Избегая проблем с округлением денежной цены, используйте целое число для представления цены в копейках. Итак, если к этим туфлям мы применим 25 %-ную скидку, то ожидаемо придем к отпускной цене 112,49:

Функция сработала. Теперь попробуем при­менить несколько недопустимых скидок. Например, 200%-ную «скидку», которая вынудит нас отдать деньги покупателю:

Когда пытаемся применить недопустимую скидку, наша программа останавливается с исключением AssertionError . Это происходит потому, что 200 %-ная скидка нарушила условие утверждения assert .

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

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

# Почему не применить обычное исключение?

Теперь подумаем, почему в предыдущем примере просто не применить инструкцию if и исключение.

Дело в том, что инструкция assert предназначена для того, чтобы сооб­щать разработчикам о неустранимых ошибках в программе. Инструкция assert не предназначена для того, чтобы сигнализировать об ожидаемых ошибочных условиях, таких как ошибка «Файл не найден», где пользователь может предпринять корректирующие действия или просто попро­бовать еще раз.

Инструкции призваны быть внутренними самопроверками (internal self­checks) вашей программы. Они работают путем объявления неких усло­вий, возникновение которых в вашем исходном коде невозможно. Если одно из таких условий не сохраняется, то это означает, что в программе есть ошибка.

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

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

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

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

  • logical_expression — это условие, которое мы проверяем,
  • error_message (не­обязательное) — это сообщение об ошибке, которое выводится на экран, если утверждение дает сбой.

Во время исполнения программы интерпретатор Python преобразовывает каждую инструкцию assert при­мерно в следующую ниже последовательность инструкций:

В этом фрагменте кода есть две интересные детали.

Перед тем как данное условие инструкции assert будет проверено, про­водится дополнительная проверка глобальной переменной __debug__ . Это встроенный булев флажок, который при нормальных обстоятельствах имеет значение True , — и значение False , если запрашивается оптимиза­ция. Мы поговорим об этом подробнее чуть позже в разделе, посвященном «распространенным ловушкам».

Кроме того, вы можете применить error_message , чтобы передать необязатель­ное сообщение об ошибке, которое будет показано в отчете об обратной трассировке вместе с исключением AssertionError . Это может еще больше упростить отладку. Например, исходный код такого плана:

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

# Ловушки assert

Есть два важных предостережения, на которые стоит обратить внимание:

  1. Первое из них связано с внесением в приложения ошибок и рисков, свя­занных с нарушением безопасности.
  2. Второе касается синтаксической причуды, которая облегчает написание бесполезных инструкций assert .

Звучит довольно ужасно (и потенциально таковым и является), поэтому вам, вероятно, следует как минимум просмотреть эти два предостереже­ния хотя бы бегло.

Не используйте инструкции assert для проверки данных!

Самое большое предостережение по поводу использования утверждений в Python состоит в том, что утверждения могут быть глобально отключены переключателями командной строки -O и -OO , а также переменной окружения PYTHONOPTIMIZE в СPython .

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

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

Поясню: если в вашей программе утверждения assert используются для проверки того, содержит ли аргумент функции «неправильное» или неожиданное значение, то это решение может быстро обернуться против вас и привести к ошибкам или дырам с точки зрения безопасности.

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

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

Приглядитесь поближе к функции delete_product . Итак, что же произой­дет, если инструкции assert будут отключены?

В этом примере трехстрочной функции есть две серьезные проблемы, и они вызваны неправильным использованием инструкций assert :

Проверка полномочий администратора инструкциями assert несет в себе опасность. Если утверждения assert отключены в интерпрета­торе Python, то проверка полномочий превращается в нулевую опера­цию. И поэтому теперь любой пользователь может удалять товары. Проверка полномочий вообще не выполняется. В результате повы­шается вероятность того, что может возникнуть проблема, связанная с обеспечением безопасности, и откроется дверь для атак, способных разрушить или серьезно повредить данные в нашем интернет-магазине. Очень плохо.

Проверка has_product() пропускается, когда assert отключена. Это означает, что метод get_product() теперь можно вызывать с недо­пустимыми идентификаторами товаров, что может привести к более серьезным ошибкам, — в зависимости от того, как написана наша программа. В худшем случае она может стать началом запуска DoS-атак. Например, если приложение магазина аварийно завершается при по­пытке стороннего лица удалить неизвестный товар, то, скорее всего, это произошло потому, что взломщик смог завалить его недопустимыми запросами на удаление и вызвать сбой в работе сервера.

Каким образом можно избежать этих проблем? Ответ таков: никогда не использовать утверждения assert для выполнения валидации данных. Вместо этого можно выполнять проверку обычными инструкциями if и при необходимости вызывать исключения валидации данных, как по­казано ниже:

Этот обновленный пример также обладает тем преимуществом, что вме­сто того, чтобы вызывать неопределенные исключения AssertionError , он теперь вызывает семантически правильные исключения, а имен­но ValueError или AuthError (которые мы должны были определить сами).

Инструкции assert , которые никогда не дают сбоя.

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

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

Например, это утверждение никогда не будет давать сбой:

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

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

На первый взгляд этот тестовый случай выглядит абсолютно приемле­мым. Однако он никогда не выловит неправильный результат: это ут­верждение assert всегда будет давать истину, независимо от состояния переменной counter . И в чем же тут дело? А в том, что оно подтверждает истинность объекта-кортежа.

Более свежие версии Python 3 для таких сомнительных инструкций assert показывают синтаксическое предупреждение.

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

# Инструкции assert — резюме

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

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

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

Инструкция assert — это средство отладки, которое проверяет условие, выступающее в качестве внутренней самопроверки вашей программы.

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

Инструкции assert могут быть глобально отключены в настройках интерпретатора.

Ветвление и условные операторы Python для начинающих

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

В случае, если мы хотим сделать что-то, только если выполняется какое-либо условие, нам придется использовать оператор if .

Проще всего будет показать, как этот оператор работает на примере. Для этого попробуем написать программу «Угадай число». Если вы начинающий программист, обязательно попробуйте именно написать эту программу, чтобы прочувствовать на практике, как это работает. Компьютер выбирает случайное число, игрок пытается угадать, программа сообщает пользователю, верен ли его ответ.

Синтаксис оператора if прост — сначала надо написать ключевое слово if , после него — условие, а в самом конце строки должно быть двоеточие.

Все строки кода, которые должны выполнится при срабатывании условия, должны быть написаны с отступом в четыре пробела относительно ключевого слова if . По отступам Python понимает, что эти строки относятся именно к if , и выполнит их только если условие будет истинным. В нашем примере, вывод строки «Угадали!» будет выполнен только если пользователь введет правильное число.

Да, про модули мы поговорим позже, но, как вы уже возможно догадались, random.randint возвращает случайное число, а строка import random загружает модуль для работы со случайными числами в нашу программу. Список того, что может этот модуль можно посмотреть вот на этой странице. Сейчас мы, однако, говорим об условиях и поэтому продолжим:

Мы добавили оператор else , который отвечает за то, чтобы выполнить какой-либо код в том случае, если не сработает оператор if . Связку этих двух операторов можно прочитать как «если какое-то условие верно, выполнить такой-то код, иначе — выполнить какой-то другой код».

Кроме операторов if и else в одной связке можно использовать оператор elif . Он пригодится, если нужно что-то посложнее реакции на верное или неверное условие. Например, нашу игру «Угадай число» можно дополнить еще двумя условиями проверки выхода введенного числа за допустимые границы:

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

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