Файл: Учебник по информатике. Программирование на Python. Основы 1 Программирование на Python. Основы.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 03.12.2023
Просмотров: 117
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
Открытый учебник по информатике. Программирование на Python. Основы
51
1 2 3 4 5 6 7 8
Чтение из файла
open(filename, mode)
Создание объекта для чтения текстового файла с путём filename. mode выставляется в зависимости от режима работы с файлом. По умолчанию файл открывается для чтения. file_obj = open(filename)
Возвращаемый в file_obj объект так же является итератором, то есть ссылается на место в файле, на котором была завершена последняя операция считывания данных. При последовательном обращении к итератору через
next() возвращаются строки файла.
next(file_obj) эквивалентно вызову file_obj.readline() (см.далее).
Пример – открытие файла для чтения. file = open('27-A.txt')
f.read(count)
Считывание следующих count символов в текстовом файле.
По умолчанию считывается весь файл.
Пример – файл test.txt содержит строку 'abcdefg'. file = open('test.txt') s = file.read(3) # 'abc' s = file.read(2) # 'de' s = file.read(5) # 'f' s = file.read(5) # ''
f.readline()
Чтение следующей несчитанной строки до переноса строки.
Если вызвать метод после считывания всего файла, будет возвращена пустая строка.
ВАЖНО: метод readline() возвращает строку с последним символом \n, кроме случая, когда это последняя строка. f.readlines()
Чтение всех несчитанных строк, разделенных переносом строки.
ВАЖНО: каждая строка в полученном списке также, как в случае с методом
readline(), оканчивается сносом строки.
Открытый учебник по информатике. Программирование на Python. Основы
52 f.close()
Удаление объекта для работы с файлом из памяти.
Данное действие закрывает файл. Тем самым позволяет открыть этот файл другим потоком. Особенно актуально закрывать файл, открытый для дозаписи.
with open(filename, flag) as f:
# обработка файла
# файл закрыт без f.close()
«Безопасный» с точки зрения работы с памятью метод чтения информации из файла. После выхода из блока команд для with объекта для работы с файлом не будет. И файл закроется автоматически.
При написании простых программ, особенно в рамках ЕГЭ, нет значительной разницы, каким образом вы работаете с файлом – удаляете ли объект после обработки всего файла или нет. После завершения работы скрипта все объекты в памяти все равно перестанут существовать.
Проблемы незакрытых файлов:
• утечка памяти для хранения объектов,
• блокировка текущей программой файла, например, если он открыт для записи,
• потеря данных в случае, если программа аварийно завершилась.
Поэтому очень важно всегда контролировать закрыт ли обработанный файл.
Также лучше использовать функции для последовательного считывания данных. Тогда при обработке файлов большого размера не будет возникать ошибок, связанных с переполнением памяти.
Так, следующие два примера хоть и делают одно и тоже, однако вариант, где мы используем метод readlines требует больше памяти и при работе с большими файлами потребует эту самую память на первоначальное считывание всех строк файла.
Не нужно выделять память на все строки из файла
Нужно выделять память на все строки из файла with open('test.txt') as f: data = list(map(int, f)) with open('test.txt') as f: data=list(map(int, f.readlines()))
Открытый учебник по информатике. Программирование на Python. Основы
53
Функции
Что такое функции
При создании сложных алгоритмов зачастую приходится иметь дело с одинаковыми участками кода, которые реализуют один и тот же служебный алгоритм. Такие участки кода принято оформлять, как функции.
Функцию можно рассматривать, как именованный участок кода, который вызывается для исполнения закодированного в нем алгоритма. Также существуют анонимные (неименованные) функции, о них поговорим ниже.
Например, если в ходе нашего алгоритма необходимо при выводе в нескольких местах форматировать строку в формате "HH:MM:SS", то мы можем описать функцию format_time_to_str(h, m, s) и вместо описания условий форматирования каждый раз вызывать описанную функцию, которая вернет нужную строку.
Такой подход локализовать ошибки, ведь при описании функции мы описываем алгоритм один раз и, в случае обнаружения ошибок его работы, исправляем ошибки в одном месте нашей программы, а не везде, где этот алгоритм был необходим.
Функции в Python можно условно разделить на те, которые возвращают значение, и те, которые его не возвращают. Первые применяются для получения результатов обработки значение, вторые для выполнения отдельных действий.
Примеры функций, которые не возвращают значение.
• Записать в файл журнала сообщение,
• Отправить сообщение в чате,
• Показать справку по команде.
Примеры функций, которые возвращают значение.
• Найти корни квадратного уравнения,
• Найти количество путей на графе по матрице смежности,
• Найти произведение матриц.
Открытый учебник по информатике. Программирование на Python. Основы
54
Функция, как и что угодно в Python, является объектом – PyFunctionObject.
Условно описание функции можно разделить на следующие составляющие:
• имя функции,
• параметры, принимаемые на вход,
• исполняемый код,
• аннотация обрабатываемых и возвращаемых значений,
• документация функции.
Правила именования функций – неразрывная строка из латинских букв в верхнем и нижнем регистрах и символов нижнего подчеркивания.
Традиционно имена функций, как и имена переменных, записываются в
«змеином» стиле – строка в нижнем регистре, слова в которой разделены знаком подчеркивания.
Пример описания функции: def func_name(x, y, z):
# блок команд
У такой функции имя func_name, и она принимает на вход 3 значения, для которых заданы имена x, y, z.
Возвращение значений
Для возвращения значения, являющимся результатом работы функции, необходимо использовать оператор return. def simple_function(): return 2 + 2
ВАЖНО: после выполнения оператор return возвращает управление тому блоку команд, в котором была вызвана функция. То есть код, записанный после оператора return выполняться не будет. def simple_function(): return 2 + 2
# этот код выполняться не будет x = 5*10
Функция может не возвращать значение. Тогда результатом выполнения функции будет объект None. def print_10(): print(10) x = print_10() # None
Открытый учебник по информатике. Программирование на Python. Основы
55
Параметры
Так как выполнение одного и того же алгоритма, который обрабатывает одинаковые значения, редко бывает полезным. Обычно гораздо проще найти значение один раз и использовать вычисленное значение далее.
Например, нет смысла постоянно находить результат вычисления значения выражения 3x
2
+10x-20 для x = 1. Гораздо полезнее, при частом обращении к данному выражению, описать функцию f(x), которая будет вычислять значение выражения для любого числового значения x.
Пример объявления функции для вычисления выражения 3x
2
+10x-20. def calc_expression(x): return 2*x**2 + 10*x – 20 print(calc_expression(5)) # 80
Стоит отметить, что есть еще один термин – аргументы. Аргументы – это значения, передаваемые на вход функции. Так, в предыдущем примере, аргументом является значение 5.
Также аргументы иногда называют фактическими параметрами.
Значения параметров по умолчанию
Также мы можем определить значения, которые будут приняты функцией, если мы не зададим их значение.
Например, мы можем определить функцию для нахождения суммы цифр в десятичной записи числа, представленного в виде строки s в системе счисления с основанием base. По умолчанию будем считать, что основание системы счисления равно 10. def sum_digit(s, base=10): str_base10 = s if base != 10: x = int(s, base) str_base10 = str(x) return sum(map(int,str_base10))
Все параметры, значения которых задаются по умолчанию, описываются последними. При этом, если количество передаваемых функции значений меньше определенного для нее количества параметров, то по умолчанию берутся параметры, начиная от последнего описанного.
Открытый учебник по информатике. Программирование на Python. Основы
56
Например, если имеем такое объявление функции def test(a, b, c=10, d=15): pass # оператор пустого блока команд
В случае передачи трех значений в качестве аргументов функции значение d будет принято по умолчанию. Если же мы передадим такой функции меньше двух значений, то интерпретатор вернет ошибку, так как все параметры должны быть определены.
При вызове функции можно задавать значение параметров по имени.
Например, для функции test() можно сделать так test(b = 10, a = 5, d = 11)
Однако обычно значения параметров без значений по умолчанию указывают в том порядке, в котором они заданы при объявлении функции. В том числе поэтому их называют позиционными.
Запрещается описывать параметры со значением по умолчанию перед описанием параметров без таковых.
Пример, как нельзя описывать параметры функции. def bad_example(a, b = 10, c): pass
ВАЖНО: объекты, на которые будут ссылаться имена аргументов, создаются
ОДИН РАЗ при инициализации функции. Это очень важно учитывать, если в качестве значения по умолчанию мы хотим определить значение изменяемого типа (например, список).
Пример. def append_to_list(x, ext_list = []): ext_list.append(x) return ext_list
Казалось бы, при передаче единственного аргумента мы будем получать список, содержащий переданное значение. Однако при вызове функции с одним значением изменяется объект, на который ссылается параметр ext_list.
Убедиться в изменении значений по умолчанию можно вызвав служебный метод __defaults__ объекта функции или проанализировав возвращаемое функцией значение. print(append_to_list.__defaults__) # ([], ) append_to_list(4) append_to_list(6) print(append_to_list.__defaults__) # ([4, 6, 8],)
Открытый учебник по информатике. Программирование на Python. Основы
57
Аннотация
Аннотация типов данных в Python [15] является больше средством для удобства разработки, чем указанием интерпретатору, какие данные будут сохранены в переменных или переданы в качестве аргументов при вызове функции. На сегодня существуют анализаторы аннотированного кода, например [16], которые указывают на несоответствие присваиваемого значения переменной типу, указанному в аннотации. Однако при запуске программы Python не проверит данные нюансы и вернет ошибку только на этапе применения не существующих операций для типа данных.
Значения переменных и параметров аннотируются следующим образом: variable_or_parameter: expression
Строго говоря, можно указывать не только тип, но и описание переменной.
Однако в основном аннотацию используют именно для указание ожидаемого типа данных для значения переменной или параметра.
Чтобы описать возвращаемый функцией результат, используется запись: def func_name() -> expression
Зачем же аннотировать ожидаемые значения, если Python все равно их проигнорирует при исполнении программы?
Такой подход повышает удобство разработки, так как большинство IDE поддерживают, например, вызов списка методов для переменных с определенным типом.
Рисунок 1. Пример подсказки для результата неаннотированной и анотированной функций
Открытый учебник по информатике. Программирование на Python. Основы
58
Также мы можем указать один из ожидаемых типов с помощью типа объединения Union из библиотеки typing. def square(x: Union[int, float]) -> Union[int, float]: return x*x
С версии 3.10 объедининие типов может быть осуществленно через оператор |. def square(x: int | float) -> int | float: return x*x
Для этого нет необходимости подключать отдельный модуль.
Документирование
Документирование функций, как и аннотация, позволяет быстрее понимать, как работать с функцией. Если аннотация, в основном, применима для описания типов обрабатываемых значений, то документирование – это описательная часть, которая раскрывает зачем нужна функция.
Документирование функций в
Python происходит согласно
docstring-соглашению [17]. Для этого используется формат описания в виде разметки reStructuredText [18], рекомендованный PEP-287 [19].
Описание работы функции записывается после её объявления в тройных кавычках. def test():
'''
My first doc
''' pass
Теперь IDE, обрабатывающий документированные функции, при наведении на функцию будут показывать написанный текст.
Рисунок 2. Пример всплывающего окна с текстом документации