Условные конструкции, булева логика и сравнения¶
В прошлых лекциях рассмотрели программы с линейной структурой: сначала выполнялась первая конструкция (например, объявление переменной), затем вторая (преобразование переменной или расчет по формуле), после – третья ( print для вывода результатов). Можно сказать, что происходило последовательное исполнение команд, причем каждая инструкция выполнялась . Но что делать, если хочется опираться на обстоятельства и принимать решения о том, выполнять одну часть кода или другую?
Допустим, по числу x нужно определить его абсолютную величину, то есть модуль. Программа должна напечатать значение переменной x , если x > 0 или же величину -x в противном случае ( -(-5) = 5 ). Эту логику можно записать следующим образом:
Исходный x меньше или равен нулю
В этой программе используется условная инструкция if (в переводе с английского «если») – это ключевое зарезервированное слово (так нельзя назвать свою переменную), указывающее на условную конструкцию. После if следует указать вычислимое выражение, которое можно проверить на истинность (то есть можно сказать, правда это или нет). Общий вид конструкции следующий:
else – тоже ключевое слово (в переводе – «иначе»). Таким образом, можно в голове придерживаться такой интерпретации: « условие верно (истинно), выполни первый блок команд, выполни второй блок».
Условная инструкция содержит как минимум ключевое слово if (единожды), затем может идти любое количество (включая ноль) блоков с условием else if (иначе если, то есть будет выполнена проверка нового условия в случае, если первая проверка в if не прошла, кратко else if записывается как elif ), затем – опционально – конструкция else . Логика чтения и выполнения кода сохраняет порядок . Как только одно из условий будет выполнено, выполнится соответствующая инструкция (или набор инструкций), а все последующие блоки будут проигнорированы. Это проиллюстрировано в коде:
Понятно, что x не может одновременно быть и больше нуля, и меньше (или равен ему). Среди всех трех print -блоков будет выполнен . Если x действительно больше нуля, то второе условие ( x < 0 ) даже не будет проверяться – Python сразу же перейдет к последней строке и выведет надпись «Такие дела!».
Чтобы лучше разобраться в том, как работает код, можно использовать – например, такой. Прогоняйте через него весь код (даже в несколько строк) и сверяйте со своими ожиданиями от его работы.
А что вообще такое эти ваши условия?¶
Выше было указано, что после конструкций if / else if / elif необходимо указать условие, которое еще и должно быть истинным или ложным («правда или нет»). Давайте попробуем определить необходимый тип переменной.
Видно, что оба условия имеют один и тот же тип — bool , то есть boolean . По определению:
Boolean (Булев, Логический тип данных) – примитивный тип данных в информатике, которые могут принимать 2 возможных значения, иногда называемых истиной (True) и ложью (False).
Оказывается, что в коде выше были получены возможные варианты булевой переменной – это истина ( True , пишется только с заглавной буквы) и ложь ( False , аналогично). Никаких других значений быть для условия не может. Вот такой это простой тип данных.
Способы получения bool ¶
Какими вообще могут быть условия? Как с ними можно обращаться? Согласно официальной документации, в Python есть такие операторы сравнения:
Здесь практически нечего рассматривать, операторы сравнения они и в Python операторы. Куда интереснее принцип – для создания комплексной логики.
Пусть стоит задача определения четверти точки по ее координатам на двумерной плоскости. Решение такой задачи может быть записано следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Пример показывает, что выполняемым блоком кода может быть любой блок Python, включая новый логический блок с if-else конструкцией. Однако его можно сократить с помощью and , or и not . Это стандартные логические операторы булевой алгебры.
Логическое является бинарным оператором (то есть оператором с двумя операндами: левым и правым) и имеет вид and . Оператор and возвращает True тогда и только тогда, когда True .
Логическое является бинарным оператором и возвращает True тогда и только тогда, когда True . Оператор «логическое ИЛИ» имеет вид or .
Логическое (отрицание) является унарным (то есть ) оператором и имеет вид not , за которым следует единственный операнд. Логическое НЕ возвращает True , False и .
Эти правила необходимо запомнить для успешного создания сложных условий с целью разделения логики, заложенной в Python-коде.
Проиллюстрируем правила в коде на простых примерах. Обратите внимание на то, как можно объявлять bool -переменные – это не сложнее, чем создание целочисленного значения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Теперь попробуем их применить на приближенных к практике примерах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Вторая четверть Is x small? False Is x large? True False True
Так как вторая переменная x_is_large – это отрицание ( not ) первой ( x_is_small ), то они не будут равны.
Блоки кода и отступы¶
В примерах выше наверняка заметили упоминание термина «блок кода», а также откуда-то взявшиеся отступы после условий, и это не случайно. Во-первых, давайте признаем, что так условные конструкции (особенно вложенные!) читать куда легче, и глаза не разбегаются. Во-вторых, это особенность языка Python – здесь не используются скобки < , >для указания блоков, все форматирование происходит с помощью отступов. Отступы добавляются в строки кода .
Для выделения блока инструкций (строк кода, выполняющихся подряд при любых условиях), относящихся к инструкциям if , else или другим, изучаемым далее, в языке Python используются . Все инструкции, которые относятся к одному блоку, должны иметь , то есть одинаковое число . В качестве отступа PEP 8 рекомендует использовать и не рекомендует использовать символ табуляции. Если нужно сделать еще одно вложение блока инструкций, достаточно добавить еще четыре пробела (см. пример выше с поиском четверти на плоскости).
Хоть и не рекомендуется использовать символ табуляции для создания отступов, кнопка Tab на клавиатуре в Jupyter -ноутбуке (при курсоре, указывающим на начало строки кода) создаст отступ в четыре пробела. Пользуйтесь этим, чтобы не перегружать клавишу пробела лишними постукиваниями.
Контекстные менеджеры¶
Контекстные менеджеры это , которые представляют из себя блоки кода, заключенные в инструкцию with . Простейшей функцией, использующей данный протокол является функция open() . Каждый раз, когда открывается файл его необходимо закрыть, чтобы записать выходные данные на диск (на самом деле Python вызывает метод close() автоматически, но явное его использование ). Например:
Чтобы каждый раз не вызывать метод close() , можно воспользоваться контекстным менеджером функции open() , который автоматически закроет файл после выхода из блока:
Для определения переменной, которая будет содержать контекстный менеджер используется инструкция as после которой идет сама переменная. Но есть и другой способ задать переменную для контекстного менеджера:
В данном случае используется оператор := .
Что же делать, если нужно вести запись в 2 файла одновременно? На помощь приходят контекстные менеджеры в круглых скобках:
В данном случае создадутся 2 файла на диске с именем file1.txt и file2.txt , которые будут содержать строчки «Hello, World 1!» и «Hello, World 2!» соответственно. Но какой ещё вид могут иметь контекстные менеджеры в круглых скобках? Вот несколько примеров как их можно использовать в коде:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
В данном разделе, все примеры содержали только одну функцию/протокол open() , так как цель раздела ознакомиться со структурой контекстного менеджера, а не с функционалом протоколов. Позже будут разбираться протоколы и как их писать с нуля.
Match-case конструкция (структурное сопоставление с шаблоном)¶
Сопоставление подразумевает определение при операторе match искомого значения, после которого можно перечислить несколько («кейсов» от слова case), каждый с оператором case . В месте обнаружения совпадения между match и case выполняется соответствующий блок кода. Например:
Здесь происходит проверка и выполнение разных операций на основе значения, которое находится внутри http_code .
Сразу становится очевидным, что «да», можно выстроить ту же логику, используя набор инструкций if-elif-else , например:
Тем не менее, с помощью инструкций match-case можно избавиться от повторения http_code == , что при тестировании на соответствие многим разным условиям.
Инструкция match-case позволяет проверять на совпадение не только тип субъекта, но и его структуру.
Если все ещё не верите в удобство этой инструкции, давайте посмотрим на пример, после которого точно не будет сомнений:
Здесь ожидается получение деталей соединения в формате кортежа и присваивание их нужным переменным.
В этом случае, если mode соединения в кортеже не определен (например, было передано только два значения – host и port ), предполагается, что режим соединения http . Тем не менее в других случаях можно ожидать, что режим будет определен явно. Тогда вместо этого будет передан кортеж вида (, , «ftp») , и mode уже не устанавливается как http , например:
Если прописать ту же логику с помощью if-elif-esle , то получится громоздкая конструкция:
Lesson 3
Условия: if-then-else
Все программы первого урока выполнялись последовательно, строка за строкой. Никакая строка не может быть пропущена.
Рассмотрим следующую задачу: для данного целого X определим ее абсолютное значение. Если X> 0, то программа должна печатать значение X, иначе оно должно печатать -X. Такое поведение невозможно достичь с помощью последовательной программы. Программа должна условно выбрать следующий шаг. Вот где помогают условия:
x = int(input()) if x > 0: print(x) else: print(-x)
Эта программа использует условный оператор if . После того if мы положим условие (x > 0) следующее двоеточием. После этого мы помещаем блок инструкций, который будет выполняться только в том случае, если условие истинно (т.е. имеет значение True ). За этим блоком может следовать слово else , двоеточие и другой блок инструкций, который будет выполняться только в том случае, если условие является ложным (т.е. имеет значение False ). В приведенном выше случае условие ложно, поэтому выполняется блок «else». Каждый блок должен иметь отступы, используя пробелы.
Подводя итог, условный оператор в Python имеет следующий синтаксис:
if condition : true-block several instructions that are executed if the condition evaluates to True else: false-block several instructions that are executed if the condition evaluates to False
Ключевое слово else с блоком «false» может быть опущено в случае, если ничего не должно быть сделано, если условие ложно. Например, мы можем заменить переменную x своим абсолютным значением следующим образом:
Отступ является общим способом в Python для разделения блоков кода. Все инструкции в одном и том же блоке должны быть отступом одинаково, т. Е. Они должны иметь одинаковое количество пробелов в начале строки. Для отступов рекомендуется использовать 4 пробела.
Отступ — это то, что делает Python отличным от большинства других языков, в которых фигурные скобки < и >используются для формирования блоков.
Кстати, встроенная функция для абсолютного значения в Python: