питон. ООП_на_Python_Учебное пособие_var5a. Методическое пособие по дисциплине Введение в компьютерные технологии Москва Физический факультет мгу имени м в ломоносова 2022
Скачать 0.51 Mb.
|
5. Логическиевыраженияиусловныеоператоры Ранее мы познакомились с тремя типами данных – целыми и вещественными числами, а также строками. Введем четвертый – логический тип данных (тип bool ). У этого типа всего два возможных значения: True и False. В программировании False обычно приравнивают к нулю, а True – к единице. Здесь также работает правило: всё, что не 0 и не пустота, является правдой. Говоря на естественном языке (например, русском) мы обозначаем сравнения словами "равно", "больше", "меньше". В языках программирования используются специальные знаки, подобные тем, которые используются в математике: > (больше), < (меньше), >= (больше или равно), <= (меньше или равно), == (равно), != (не равно). 8 Не путайте операцию присваивания значения переменной, обозначаемую в языке Python одиночным знаком "равно", и операцию сравнения (два знака "равно"). Присваивание и сравнение – разные операции. a = 10 b = 5 c = a+b > 14 print(c) # вывод: True c = a < 14-b print(c) # вывод: False c = a <= b+5 print(c) # вывод: True c = a != b print(c) # вывод: True c = a == b print(a, b, c) # вывод: 10 5 False Логические выражения типа kByte >= 1023 являются простыми, так как в них выполняется только одна логическая операция. Однако, на практике нередко возникает необходимость в более сложных выражениях. Может понадобиться получить ответа "Да" или "Нет" в зависимости от результата выполнения нескольких простых выражений. В таких случаях используются специальные операторы, объединяющие два и более простых логических выражения. Широко используются два оператора – так называемые логические И(and) иИЛИ (or). Чтобы получить True при использовании оператора and, необходимо, чтобы результаты обоих простых выражений, которые связывает данный оператор, были истинными. Если хотя бы в одном случае результатом будет False, то и все выражение будет ложным. x = 8 y = 13 print(y < 15 and x > 8) # вывод: False Чтобы получить True при использовании оператора or, необходимо, чтобы результат хотя бы одного простого выражения, входящего в состав сложного, был истинным. В случае оператора or выражение становится ложным лишь тогда, когда ложны оба составляющие его простые выражения. x = 8 y = 13 print(y < 15 or x > 8) # вывод: True В языке Python есть еще унарный логический оператор not , то есть отрицание. Он превращает правду в ложь, а ложь в правду. Унарный он потому, что применяется к одному выражению, стоящему после него. print(not y < 15) # вывод: False При выполнении кода, в зависимости от тех или иных условий, некоторые его участки могут быть опущены, в то время как другие – выполнены. Иными словами, в программе может присутствовать ветвление, которое реализуется условным оператором, который имеет следующий формат: if <Логическое выражение> : <Блок, выполняемый, если условие истинно> [ elif <Логическое выражение> : <Блок, выполняемый, если условие истинно> ] [ else : <Блок, выполняемый, если все условия ложны> ] Python считается языком с ясным синтаксисом и легко читаемым кодом. Это достигается сведением к минимуму таких вспомогательных элементов как скобок и точек 9 с запятой. Для разделения выражений используется переход на новую строку, а для обозначения вложенных выражений – отступы от начала строки: a = 50 n = 98 if n < 100 : b = n + a #блок выполняемый, если условие истинно else : b=0 #блок выполняемый, если условие ложно print(b) #вывод 148 Последняя строчка кода print(b) уже не относится к условному оператору, что обозначено отсутствием перед ней отступа. В язык Python встроена возможность настоящего множественного ветвления на одном уровне вложенности, которое реализуется с помощью веток elif. Слово "elif" образовано от двух первых букв слова "else", к которым присоединено слово "if". Это можно перевести как "иначе если". В отличие от else , в заголовке elif обязательно должно быть логическое выражение также, как в заголовке if: old = int (input( 'Ваш возраст: ' )) print( 'Рекомендовано:' , end= ' ' ) if old < 6: print( '"Заяц в лабиринте"' ) elif 6 <= old < 12: print( '"Марсианин"' ) elif 12 <= old < 16: print( '"Загадочный остров"' ) else : print( '"Поток сознания"' ) 6. Списки Список в Python – это встроенный тип (класс) данных, представляющий собой одну из разновидностей структур данных. Структуру данных можно представить, как сложную единицу, объединяющую в себе группу более простых. Каждая разновидность структур данных имеет свои особенности. Список – это изменяемая последовательность произвольных элементов. В большинстве других языков программирования есть такой широко используемый тип данных как массив. В Питоне такого встроенного типа нет. Однако списки условно можно считать аналогом массивов за одним исключением. Составляющие массив элементы должны принадлежать одному типу данных, для списков такого ограничения нет. Например, массив может содержать только целые числа или только вещественные числа или только строки. Список также может содержать элементы только одного типа, что делает его внешне неотличимым от массива. Но вполне допустимо, чтобы в одном списке содержались как числа, так и строки, а также что-нибудь еще. Создавать списки можно разными способами. Создадим его простым перечислением элементов: a = [12, 3.85, "black" , -4] Итак, у нас имеется список, присвоенный переменной a. В Python список определяется квадратными скобками. Он содержит четыре элемента. Если где-то в программе нам понадобится весь этот список, мы получим доступ к нему, указав всего лишь одну переменную – a. Элементы в списке упорядочены, имеет значение в каком порядке они расположены. Каждый элемент имеет свой индекс, или номер. Индексация начинается с нуля. В данном 10 случае число 12 имеет индекс 0, строка "black" – индекс 2. Чтобы извлечь конкретный элемент, надо после имени переменной указать в квадратных скобках его индекс: print(a[0]) В Python существует также индексация с конца. Она начинается с -1: print(a[-1]) Часто требуется извлечь не один элемент, а так называемый срез – часть списка. В этом случае указывается индекс первого элемента среза и индекс следующего за последним элементом среза: print(a[0:2]) # [12, 3.85] В данном случае извлекаются первые два элемента с индексами 0 и 1. Элемент с индексом 2 в срез уже не входит. В таком случае возникает вопрос, как извлечь срез, включающий в себя последний элемент? Если какой-либо индекс не указан, то считается, что имеется в виду начало или конец: print(a[:3]) # [12, 3.85, 'black'] print(a[2:]) # ['black',-4] print(a[:]) # [12, 3.85, 'black',-4] Списки – изменяемые объекты. Это значит, что в них можно добавлять элементы, удалять их, изменять существующие. Проще всего изменить значение элемента. Для этого надо обратиться к нему по индексу и перезаписать значение в заданной позиции: a[1] = 4 Добавлять и удалять лучше с помощью специальных встроенных методов списка: a.append( 'wood' ) a.insert(1, 'circle' ) a.remove(4) a.pop() a.pop(2) Перечень всех методов списка можно посмотреть в интернете, например, на официальном сайте https://docs.python.org/3/tutorial/datastructures.html Можно изменять списки не используя методы, а с помощью взятия и объединения срезов: b = [1, 2, 3, 4, 5, 6] b = b[:2] + b[3:] Здесь берется срез из первых двух элементов и срез, начиная с четвертого элемента (индекс 3) и до конца. После чего срезы объединяются с помощью оператора "сложения". Можно изменить не один элемент, а целый срез: mylist = [ 'ab' , 'ra' , 'ka' , 'da' , 'bra' ] mylist[0:2] = [10,20] print(mylist) # [10, 20, 'ka', 'da', 'bra'] 7. Циклы Циклы являются такой же важной частью структурного программирования, как условные операторы. С помощью циклов можно организовать повторение выполнения участков кода. Язык Python при помощи циклов позволяет компактно записать многие повторяющиеся действия, например, вывод чисел от 1 до 100: for x in range (1, 101): print(x) Цикл for применяется для перебора элементов последовательности и имеет такой формат: 11 for <Текущий элемент> in <Последовательность> : <Инструкции внутри цикла> [ else : <Блок, выполняемый, если не использовался оператор break > ] Здесь присутствуют следующие конструкции: • <Последовательность> – объект, поддерживающий механизм итерации (последовательного перебора): строка, список, кортеж, диапазон, словарь и др. • <Текущий элемент> – на каждой итерации через эту переменную доступен очередной элемент последовательности или ключ словаря. • <Инструкции внутри цикла> – блок, который будет многократно выполняться. • Если внутри цикла не использовался оператор break, то после завершения выполнения цикла будет выполнен блок в инструкции else. Этот блок не является обязательным. Пример перебора букв в слове: for symbol in "string" : print(symbol, end= " " ) else : print( "\nЦикл выполнен" ) Функцией range () используется для генерации индексов. Она имеет следующий формат: range ([<Начало>, ]<Конец>[, <Шаг>]) Первый параметр задает начальное значение. Если параметр <Начало> не указан, то по умолчанию используется значение 0. Во втором параметре указывается конечное значение. Следует заметить, что оно не входит в возвращаемые значения. Если параметр <Шаг> не указан, то используется значение 1. Функция возвращает диапазон – особый объект, поддерживающий итерационный протокол. С помощью диапазона внутри цикла for можно получить значение текущего элемента. В качестве примера умножим каждый элемент списка на 2: arr = [1, 2, 3] for i in range (len (arr) ) : arr[i] *= 2 print (arr) # вывод [2,4,6] Цикл while Выполнение инструкций в цикле while продолжается до тех пор, пока логическое выражение истинно. Он имеет следующий формат: while <Условие> : <Инструкции> [ else : <Блок, выполняемый, если не использовался оператор break > ] Последовательность работы цикла while следующая. Инструкции внутри цикла выполняются пока условие истинно. При этом истинность условия проверяется перед каждой итерацией цикла. Выход из цикла осуществляется либо если условие не прошло очередную проверку на истинность, что может случиться и на входе в цикл, либо если встречается оператор break. Опционально можно дополнить цикл while, блоком else, инструкции в котором выполнятся по завершении цикла, при условии, что не сработал оператор break. В отличии от цикла for, единственная возможность которого пробежаться по итерируемому объекту,цикл while позволяет писать циклы, выход из которых осуществляется при более сложных обстоятельствах. 12 В качестве примера, рассмотрим поиск наибольшего общего знаменателя методом Эвклида, итерации которого выполняются до тех пор, пока наименьшее из чисел не равно нулю. x, y = 60, 48 while y: x, y = y, x % y print(x) # вывод 12 Нередко цикл while комбинируют с счетчиком. Тогда он принимает следующий формат: <3адание начального значения для переменной - счетчика> while <Условие> : <Инструкции> <Приращение значения в переменной - счетчике> [ else : <Блок, выполняемый, если не использовался оператор break > ] Последовательность его работы сводится к: 1. Переменной-счетчику присваивается начальное значение. 2. Проверяется условие, если оно истинно, то выполняются инструкции внутри цикла, иначе выполнение цикла завершается. 3. Переменная-счетчик изменяется на величину, указанную в параметре <приращение>. 4. Переход к пункту 2. 5. Если внутри цикла не использовался оператор break, то после завершения выполнения цикла будет выполнен блок в инструкции else . Этот блок не является обязательным. Создадим пустой список и заполним его в цикле случайными числами: import random # модуль генерации случайных чисел c = [] i = 0 while i < 10: c.append( random .randint(0,100)) i += 1 print(c) Оператор continue позволяет перейти к следующей итерации цикла до завершения выполнения всех инструкций внутри цикла. В качестве примера выведем все числа от 1 до 100, кроме чисел от 5 до 10 включительно: for i in range (1,101): if 4 < i < 11 : continue # Переходим на следующую итерацию цикла print(i) Оператор break позволяет прервать выполнение цикла досрочно. Для примера выведем все числа от 1 до 100 еще одним способом: i = 1 while True: if i > 100: break # Прерываем цикл print(i) i += 1 Цикл while совместно с оператором break удобно использовать для получения неопределенного заранее количества данных от пользователя. В качестве примера просуммируем произвольное количество чисел: 13 print( "Введите слово 'stop' для получения результата" ) summa = 0 while True : x = input( "Введите число: " ) if x == "stop" : break # Выход из цикла x = int (x) # Преобразуем строку в число summa += x print( "Сумма чисел равна:" , summa) 8. Функции Функция в программировании представляет собой обособленный участок кода, который можно вызывать, обратившись к нему по имени, которым он был назван. При вызове происходит выполнение команд тела функции. Функции можно сравнить с небольшими программками, которые сами по себе, то есть автономно, не исполняются, а встраиваются в обычную программу. Нередко их так и называют – подпрограммы. Других ключевых отличий функций от программ нет. Функции также при необходимости могут получать и возвращать данные. Только обычно они их получают не с ввода (клавиатуры, файла и др.), а из вызывающей программы. Сюда же они возвращают результат своей работы. Существует множество встроенных в язык программирования функций. С некоторыми такими в Python мы уже сталкивались. Это print(), input(), int(), float(), str(), type(). Код их тела нам не виден, он где-то "спрятан внутри языка". Нам же предоставляется только интерфейс – имя функции. С другой стороны, программист всегда может определять свои функции. Их называют пользовательскими. В языке программирования Python функции определяются с помощью оператора def . Рассмотрим код: def count_food(): a = int (input()) b = int (input()) print( "Всего" , a+b, "шт." ) Это пример определения функции. Как и другие сложные инструкции вроде условного оператора и циклов функция состоит из заголовка и тела. Заголовок оканчивается двоеточием и переходом на новую строку. Тело имеет отступ. Ключевое слово def сообщает интерпретатору, что перед ним определение функции. За def следует имя функции. Оно может быть любым, так же, как и всякий идентификатор. В программировании весьма желательно давать всему осмысленные имена. Так в данном случае функция названа "посчитать_еду" в переводе на русский. После имени функции ставятся скобки. В приведенном примере они пустые. Это значит, что функция не принимает никакие данные из вызывающей ее программы. Однако она могла бы их принимать, и тогда в скобках были бы указаны параметры этой функции. После двоеточия следует тело, содержащее инструкции, которые выполняются при вызове функции. Следует различать определение функции и ее вызов. В программном коде они не рядом и не вместе. Можно определить функцию, но ни разу ее не вызвать. Нельзя вызвать функцию, которая не была определена. Определив функцию, но ни разу не вызвав ее, вы никогда не выполните ее тела. 14 def count_food(): a = int (input()) b = int (input()) print( "Всего" , a+b, "шт." ) print( "Сколько бананов и ананасов для обезьян?" ) count_food() print( "Сколько жуков и червей для ежей?" ) count_food() print( "Сколько рыб и моллюсков для выдр?" ) count_food() В языке Python определение функции должно предшествовать ее вызовам. Это связано с тем, что интерпретатор читает код строка за строкой и о том, что находится ниже по течению, ему еще неизвестно. Поэтому если вызов функции предшествует ее определению, то возникает ошибка (выбрасывается исключение NameError ). Польза функций не только в возможности многократного вызова одного и того же кода из разных мест программы. Не менее важно, что благодаря им программа обретает истинную структуру. Функции как бы разделяют ее на обособленные части, каждая из которых выполняет свою конкретную задачу. Функции могут передавать какие-либо данные из своих тел в основную ветку программы. Говорят, что функция возвращает значение. В большинстве языков программирования, в том числе Python, выход из функции и передача данных в то место, откуда она была вызвана, выполняется оператором return . Если интерпретатор Питона, выполняя тело функции, встречает return , то он "забирает" значение, указанное после этой команды, и "уходит" из функции. def cylinder(): r = float (input()) h = float (input()) # площадь боковой поверхности цилиндра: side = 2 * 3.14 * r * h # площадь одного основания цилиндра: circle = 3.14 * r**2 # полная площадь цилиндра: full = side + 2 * circle return full square = cylinder() print(square) В Питоне позволительно возвращать из функции несколько объектов, перечислив их через запятую после команды return: def cylinder(): r = float (input()) h = float (input()) side = 2 * 3.14 * r * h circle = 3.14 * r**2 full = side + 2 * circle return side, full sCyl, fCyl = cylinder() print( "Площадь боковой поверхности %.2f" % sCyl) print( "Полная площадь %.2f" % fCyl) Из функции cylinder() возвращаются два значения. Первое из них присваивается переменной sCyl, второе – fCyl. Фокус здесь в том, что перечисление значений через запятую (например, 10, 15, 19) создает объект типа tuple. На русский переводится как "кортеж". Когда же кортеж присваивается сразу нескольким переменным, то происходит сопоставление его элементов соответствующим в очереди переменным. Это называется распаковкой. 15 Таким образом, когда из функции возвращается несколько значений, на самом деле из нее возвращается один объект класса tuple. Перед возвратом эти несколько значений упаковываются в кортеж. Если же после оператора return стоит только одна переменная или объект, то ее/его тип сохраняется как есть. Функции могут не только возвращать данные, но также принимать их, что реализуется с помощью так называемых параметров, которые указываются в скобках в заголовке функции. Количество параметров может быть любым. Параметры представляют собой локальные переменные, которым присваиваются значения в момент вызова функции. Конкретные значения, которые передаются в функцию при ее вызове, называются аргументами. Когда функция вызывается, то ей передаются фактические значения аргументов. Т.е. переменным-параметрам присваиваются переданные в функцию значения. Соответственно, изменение значений в теле функции никак не скажется на значениях фактических переменных. Они останутся прежними. В Python такое поведение характерно для неизменяемых типов данных, к которым относятся, например, числа и строки. Существуют изменяемые типы данных. Для Питона, это, например, списки и словари. В этом случае данные передаются по ссылке. В функцию передается ссылка на них, а не сами данные. И эта ссылка связывается с локальной переменной. Изменения таких данных через локальную переменную обнаруживаются при обращении к ним через глобальную. Это есть следствие того, что несколько переменных ссылаются на одни и те же данные, на одну и ту же область памяти. Необходимость передачи по ссылке связана в первую очередь с экономией памяти. Сложные типы данных, по сути представляющие собой структуры данных, обычно копировать не целесообразно. Однако, если надо, всегда можно сделать это принудительно. |