Файл: Тема Основы языка Python.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.12.2023

Просмотров: 130

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

27
Если запустить эту программу, можно легко убедиться в том, что 0.1 +
0.2 не равно 0.3. Хотя можно было надеяться, что несмотря на неточное представление, оно окажется одинаково неточным для всех чисел.
Поэтому при использовании вещественных чисел нужно следовать простым правилам:
1. Если можно обойтись без использования вещественных чисел, нужно это сделать. Вещественные числа проблемные, неточные и медленные.
2. Два вещественных числа равны между собой, если они отличаются не более чем на epsilon. Число X меньше числа Y, если
X < Y – epsilon.
Код для сравнения двух чисел, заданных с точностью 6 знаков после точки, выглядит так, как представлено на рис. 36.
Рис. 36. Сравнение двух чисел
Если над числами совершались какие-то действия, то значения epsilon нужно вычислять. В учебных задачах это можно сделать не внутри программы, а один раз вручную для худшего случая, и применять вычисленное значение как константу.
Округление вещественных чисел
При использовании целых и вещественных чисел в одном выражении вычисления производятся в вещественных числах. Тем не менее иногда возникает необходимость преобразовать вещественное число в целое. Для этого можно использовать несколько видов функций округления:
− int – округляет в сторону нуля (отбрасывает дробную часть);

28
− round – округляет до ближайшего целого. Если ближайших целых несколько (дробная часть равно 0.5), то к чётному;
− floor – округляет в меньшую сторону;
− ceil – округляет в большую сторону.
Примеры для различных чисел приведены в табл. 3.
Таблица 3
Сравнение функций округления
Функция
2.5
3.5
–2.5 int
2 3
–2 round
2 4
–2 floor
2 3
–3 ceil
3 4
–2
Функции floor и ceil находятся в библиотеке math. Есть два способа получить возможность воспользоваться ими в своей программе.
В первом способе импортируется библиотека math, тогда перед каждым вызовом функции оттуда нужно писать слово «math.», а затем – имя функции (рис. 37).
Рис. 37. Использование округления
Во втором способе из библиотеки импортируются некоторые функции, и доступ к ним можно получить без написания «math.» (рис. 38).

29
Рис. 38. Использование округления
Второй способ предпочтительно применять в случае, если какие-то функции используются часто и нет конфликта имен (функций с одинаковыми именами в нескольких подключенных библиотеках).
В библиотеке math также есть функция округления trunc, которая работает аналогично int.
Срезы строк
Нам известны способы считывать, выводить и задавать константные строки, а также склеивать строки между собой и умножать строку на число.
Чтобы определить длину строки s, можно воспользоваться функцией len(s). Она возвращает целое число, равное длине строки.
Срез – это способ извлечь из строки отдельные символы или подстроки. При применении среза конструируется новая строка. Строка, к которой был применён срез, остается без изменений.
Простейший вид среза – это обращение к конкретному символу строки по номеру. Чтобы получить i-ый символ строки, нужно написать s[i]. В результате этого будет сконструирована строка, содержащая только один символ – тот, который стоял на месте i. Нумерация символов идет с нуля.
При попытке обратиться к символу с номером, больше либо равным длине строки, возникает ошибка.
В языке Питон присутствует и нумерация символов строки отрицательными числами. Последний символ строки имеет номер –1, предпоследний –2 и так далее. При попытке обратиться к символу с номером, меньшим –len(s), возникает ошибка.


30
Нумерация символов в строке
«
String
»
представлена в табл. 4.
Таблица 4
Нумерация символов в строке «String»
S
t
r
i
n
g
0 1
2 3
4 5
–6
–5
–4
–3
–2
–1
Получить доступ, например, к символу n можно двумя способами: s[4] и s[–2].
Также существуют срезы с двумя параметрами: в результате применения среза s[
a:b
] будет сконструирована подстрока, начиная с символа на позиции a и заканчивая символом на позиции b-1
(правая граница не включается). Каждый из индексов может быть как положительным, так и отрицательным.
Например, при s =
"String", s[
1:5
] будет равно "trin", это можно было бы записать и как s[
1:–1
]. Если в качестве второго числа в срезе взять число, больше либо равное длине строки, то ошибки не возникнет, и будут взяты все символы до конца строки.
Если нужно взять все символы строки, начиная с позиции a и до конца, то второй параметр можно опускать. Например, s[2:] будет равно "ring".
Если опустить первый параметр в срезе, то будет взята подстрока с начала, например s[:2] будет равно "St".
Если же написать S[:], то будет взята вся строка от начала до конца.
Если первый параметр находится правее второго, то будет сгенерирована пустая строка.
Существует срез с тремя параметрами, где третий параметр задает шаг, с которым нужно брать символы. Например, можно взять все символы с начала до конца с шагом 2. Это будет выглядеть как s[::2]. В результате получится строка "Srn".
Естественно, первый и второй параметры можно не

31 опускать. Если третий параметр не указан, т. е. в квадратных скобках записано только одно двоеточие, то шаг считается равным 1.
Шаг в срезе может быть и отрицательным. В таком случае первый параметр должен находиться правее второго. Например, s[5:1:–2] даст строку "gi"
– 5-ый и 3-ий символы, а символ с номером 1 уже не входит.
Развернутую строку можно получить срезом s[::–1] – все символы от
«начала» до «конца» в обратном порядке. Если третий параметр отрицательный, то началом среза считается последний символ, а концом – позиция перед нулевым символом.
Метод find
Методы – это функции, применяемые к объектам. Метод вызывается с помощью записи
ИмяОбъекта.НазваниеМетода(Параметры).
Методы очень похожи на функции, но позволяют лучшим образом организовывать хранение и обработку данных. Например, вы написали свою структуру данных и хотели бы, чтобы функция len возвращала длину вашей структуры.
Чтобы это заработало, придется лезть в исходный код интерпретатора
Питона и вносить изменения в функцию len. Если бы len было методом, то вы могли бы описать этот метод при создании структуры, и никаких изменений в коде интерпретатора или стандартной библиотеки не потребовалось бы. Поэтому методы предпочтительнее для сложных структур, таких, например, как строки.
У строк есть множество различных методов. В этом разделе мы рассмотрим методы поиска подстроки в строке. Метод find возвращает индекс первого вхождения подстроки в строку, а если она не нашлась, то –1
Например, 'String'.find('ing') вернет 3 – индекс, с которого начинается вхождение подстроки ing.
Существуют модификации этих методов с двумя параметрами. s.find(substring, from) будет осуществлять поиск в подстроке s[from:].
Например, 'String'.find('ing', 1) вернет 3 (остается нумерация символов, как в


32 исходной строке). По аналогии со срезами параметры могут быть и отрицательными.
Есть модификации с тремя параметрами, они ищут подстроку в срезе s[
a:b
].
Часто возникает задача найти и вывести все вхождения подстроки в строку, включая накладывающиеся. Например, для строки 'ABABA' и подстроки 'ABA' ответ должен быть 0, 2. Ее решение выглядит так, как представлено на рис. 39.
Рис. 39. Использование метода find
Методы rfind, replace и count
Метод rfind работает аналогично find, но ищет самое правое вхождение.
Метод replace(old, new) позволяет заменить все вхождения подстроки old на подстроку new. При этом конструируется новая строка, где были произведены замены. Нужно обратить внимание, что метод replace заменяет вхождения подстрок без учета предыдущих совершенных замен. Если далее применить операцию 'AAAAAA'.replace('AA', 'A'), то в результате получится строка 'AAA', а не 'A', как можно было бы ожидать.
Фактически можно считать, что метод replace находит очередное вхождение подстроки old, осуществляет замену и продолжает поиск с позиции после всех замененных символов (без наложения и поиска в замененной части
).
Существует модификация replace(old, new, count), которая осуществляет не более count замен самых левых вхождений подстроки old.

33
Для строк существует метод count, который позволяет подсчитать количество вхождений подстроки. По аналогии с методом find определены методы count с двумя и тремя параметрами.
1.4. Создание функции для работы с данными
Функции
Функции – части программы, которые можно повторно вызывать с разными параметрами, чтобы не писать много раз одно и то же. Функции в программировании немного отличаются от математических функций. В математике функции могут только получить параметры и дать ответ, в программировании же функции умеют делать что-нибудь полезное, например ничего не возвращать, но что-то печатать.
Функции чрезвычайно полезны, если одни и те же действия нужно выполнять несколько раз. Но некоторые логические блоки работы с программой иногда тоже удобно оформлять в виде функции. Это связано с тем, что человек может одновременно держать в голове ограниченное количество вещей. Когда программа разрастается, отследить все очень сложно. В пределах одной небольшой функции запутаться гораздо сложнее: известно, что она получает на вход, что должна выдать, а об остальной программе в это время можно не думать.
В программировании считается хорошим стилем писать функции, умещающиеся на один экран. Тогда можно одновременно окинуть взглядом всю функцию. Поэтому, если получилась очень длинная запись, нужно нарезать ее на кусочки так, чтобы каждый из них был логичным (делал какое-то определенное действие, которое можно назвать) и не превышал 10–
15 строк.
Мы уже использовали готовые функции, такие как print, len и некоторые другие. Эти функции описаны в стандартной библиотеке или


34 других подключаемых библиотеках. Сегодня мы научимся создавать свои функции.
Использование функций
Рассмотрим, как создать свою функцию, на примере вычисления факториала. Текст программы без функции выглядит так, как представлено на рис. 40.
Рис. 40. Текст программы без функции
Вычисление факториала можно вынести в функцию, тогда эта же программа будет выглядеть, как на рис. 41.
Рис. 41. Текст программы c функцbtq
Описание функции должно идти в начале программы. На самом деле оно может быть в любом месте до первого вызова функции factorial.
Определение функции должно начинаться со слова def (сокращение от
«define» – определить). Дальше идет имя функции, после которого в скобках

35 через запятую перечисляются параметры (у нашей функции всего один параметр). После закрытия скобки должно стоять двоеточие.
Команды, выполняемые в функции, должны записываться с отступом, как в блоках команд if или while.
В нашей функции num – это параметр, на его место подставляется то значение, с которым функция была вызвана. Действия внутри функции точно такие же, как в обычной программе, кроме дополнительной команды return.
Команда return возвращает значение функции (оно должно быть записано через пробел после слова return) и прекращает её работу. Возвращенное значение подставляется на то место, где осуществлялся вызов функции.
Команда return может встречаться в любом месте функции. После того как она выполнится, работа функции будет прекращена. Здесь есть некоторая аналогия с командой break, применяемой для выхода из цикла.
Вызовы функций из функции
Функцию подсчета факториала можно использовать для подсчета биномиальных коэффициентов (числа сочетаний). Формула для подсчета числа сочетаний выглядит так: n! / (k! * (n – k)!).
Если бы мы не пользовались функциями, то нам потребовалось бы три раза записать почти одно и то же. С помощью функций вычисление выглядит намного проще (рис. 42).
Рис. 42. Пример использования функции factorial
Подсчет биномиальных коэффициентов можно также оформить в виде функции с двумя параметрами (рис. 43).

36
Рис. 43. Пример задания функции
Возврат значений
Как было сказано выше, выполнение функции прерывается по команде return. Для примера рассмотрим функцию поиска максимума из двух чисел, которые передаются ей в качестве параметров (рис. 44).
Рис. 44. Пример задания функции
Её можно было бы записать и по-другому (рис. 45).
Рис. 45. Пример задания функции
Если условие в if'е было истинным, то выполнится команда return a, выполнение функции будет прекращено, до команды return b выполнение просто не дойдет.
С помощью функции max2 можно реализовать функцию max3, возвращающую максимум из трех чисел (рис. 46).


37
Рис. 46. Пример задания функции
Эта функция дважды вызывает max2: сначала для выбора максимума среди чисел a и b, а затем для выбора максимума между найденным значением и оставшимся числом c.
Здесь нужно обратить внимание, что в качестве аргумента функции может передаваться не только переменная или константное значение, но и результат вычисления любого арифметического выражения. Например, результат, возвращенный другой функцией.
Функции max2 и max3 будут работать не только для чисел, но и для любых сравнимых объектов, например для строк.
Возврат нескольких значений функцией
Рассмотрим случай, когда функция должна вернуть несколько значений, на примере функции, упорядочивающей два числа. Чтобы вернуть несколько значений, достаточно записать их в return через запятую.
Аналогично через запятую должны быть перечислены переменные, в которые будут попадать вычисленные значения (рис. 47).
Рис. 47. Пример задания функции
На самом деле при перечислении значений через запятую формируются объекты типа «кортеж» (их подробное изучение – в следующей лекции).

38
Имеющихся знаний достаточно для использования функций, возвращающих несколько значений.
Возврат логических значений
Иногда удобно оформлять даже простые вещи в виде функций, чтобы повысить читаемость программы. Например: если нужно проверить число на четность, то гораздо понятнее будет вызывать функцию isEven(n), а не писать каждый раз n % 2 == 0.
Такая функция может выглядеть так, как представлено на рис. 48.
Рис. 48. Пример задания функции
Результатом работы этой функции будет истина или ложь. Теперь функцию очень удобно применять в if'ах (рис. 49).
Рис. 49. Пример использования заданной функции
Если есть сложное логическое выражение, то лучше оформить его в виде функции с говорящим названием. Так программу будет легче читать, а вероятность ошибок в ней резко снизится.
Локальные и глобальные переменные
Все переменные, которыми мы пользовались до настоящего момента, были глобальными. Глобальные переменные видны во всех функциях программы.

39
Например, такой код напечатает 1и выполнится без ошибок (рис. 50).
Рис. 50. Обращения к глобальной переменной
Переменная a
– глобальная, поэтому мы можем смотреть на её значение из любой функции. На момент вызова функции f переменная a уже создана, хотя описание функции и идет раньше присваивания.
Если же инициализировать переменную внутри функции, то использовать её вне функции невозможно. Например, код на рис. 51 завершится с ошибкой «builtins.NameError: name 'a' is not defined»
(переменная a не определена).
Рис. 51. Объявление переменной внутри функции
Переменные, значения которых изменяются внутри функции по умолчанию, считаются локальными, т. е. доступными только внутри функции. Как только функция заканчивает свою работу, переменная уничтожается.
Таким образом, если в функции происходило присваивание какой-то переменной, то эта переменная считается локальной. Если присваиваний не происходило, то переменная считается глобальной.
Локальные переменные можно называть такими же именами, как и глобальные. Например, вывод такого кода будет «1 0» (рис. 52).