Функции
Мы зачастую хотим делить нашу программу на составные блоки, это могут быть модули/пакеты модулей, классы для написания программ в парадигме ООП. Одним из составных блоков нашей программы может быть функция.
Если говорить просто, то функция – это средство, позволяющее группировать наборы инструкций так, что в программе они могут запускаться неоднократно. Функции могут вычислять некоторый результат и позволять указывать вход- ные параметры, отличающиеся по своим значениям от вызова к вызову. Воз- можность оформления операций в виде функций – это очень удобный инстру- мент, который мы можем использовать в самых разных ситуациях.
Для объявления функций используется инструкция def. Пример простой функции с именем foo, которая ничего не делает
Функции получают аргументы. Аргументы мы перечисляем в круглых скобочках.
Вызов функций
Для вызова функции(т.е перехода к исполнению ее инструкций) используется оператор вызова функции:
Возврат значения из функции / оператор return
Наши функции делают какую-то работу, мы это работу хотим из функции получить, для того чтобы вернуть значение из функции используется оператор return
Если мы явно ничего из функции не возвращали - из функции вернется None
Помимо этого инструкция return прекращает дальнейшее исполнение функции и мы можем исползовать return без указания возвращаемого значения:
Аргументы функции
- Позиционные аргументы - аргументы передаваемые при вызове по их порядку в объявлении функции
 - Именованные аргументы - аргументы передаваемые по их имени, указанному при объвлении функции
 
Аргументы со значением по умолчанию (Опициональные)
Если вы объявили функцию с 2 аргументами и не указали значения по умолчанию - эти аргументы будут обязательными при вызове функции, для объявления функции с опциональными аргументами используется следующий синтаксис:
В примере мы создали функцию foo, которая получает один аргумент, но он не является обязательным, потому что для него указано значение по умолчанию("default value")
❗️Обратите внимание
Значения по умолчанию инициализируются во время инициализации функции, в других языках, которые я знаю значение по умолчанию инициализируется при каждом вызове функции, это может приводить к неблагоприятным сайд-эффектам.
Для большей ясности я продемонстрирую вам пример:def addvalue(value, target_list= []):"""Функция добавляющая значение в лист и возвращающая его, зачем она это делает?.. не будем углублятьсяНо интересный факт, что если лист не передан вторым аргументом по умолчанию будет использоваться значение по умолчанию"""target_list.append(value)return target_listprint(addvalue(1)) # что ожидаем увидеть? Ну правильно! [1]print(addvalue(2)) # а здесь что будет? Должно быть неожиданным, но вернет она [1,2]Живой примерчик:
Сворачивание аргументов
Нам было бы не удобно если функции могли получать только ограниченное кол-во аргументов, поэтому мы можем делать сворачивание аргументов. Для начала рассмотрим пример функции sum которая получает только 2 аргумента и возвращает их сумму:
Но что делать если мы хотим вызывать функцию с несколькими аргументами?
В таком случае давайте сделаем так, чтобы все позиционные аргументы собирались в какую-то одну переменную-аргумент, назовем ее args. Для сворачивания аргуметов используется символ *
Вполне естественно для понимания, что переменная args внутри функции будет типа tuple. Примерно такое же вы можете делать и для именованных аргументов
Для того чтобы свернуть все оставшиеся именованные аргументы используется синтаксис с двумя звездочками **. А тип переменной kwargs будет dict.
Только позиционные и только именованные аргументы
⚠️Важно заметить
Только позиционныеаргументы появились вPython 3.8
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):----------- ---------- ----------| | || Positional or keyword || - Keyword only-- Positional only
Только именованные
Для того чтобы сделать аргументы только именованными нам надо просто воспользоваться сворачиванием позиционных аргументов через * или *args. Все перечисленные аргументы полсле сворачивания будут передаваться только по имени.
Только позиционные
Для того чтобы сделать аргументы только позиционными они отделяются символом /. (Как показано в примере выше)
Что делает def?
Давайте теперь рассмотрим что делает оператор def, и для того чтобы меньше самому писать я обращусь к Лутцу.
def– это исполняемый программный код. Функции в языкеPythonсоздаются с помощью новой инструкцииdef. В отличие от функций в компилирующих языках программирования, таких какC,defотносится к классу исполняемых инструкций – функция не существует, пока интерпретатор не доберется до инструкции def и не выполнит ее. Фактически вполне допу- стимо (а иногда даже полезно) вкладывать инструкцииdefвнутрь инструкцийif, цикловwhileи даже в другие инструкцииdef. В случае наиболее типичного использования инструкцииdefвставляются в файлы модулей и генерируют функции при выполнении во время первой операции импор- тирования.defсоздает объект и присваивает ему имя. Когда интерпретаторPythonвстречает и выполняет инструкциюdef, он создает новыйобъект-функциюи связывает его с именем функции. Как и в любой другой операции при- сваивания, имя становится ссылкой на объект-функцию. В имени функции нет ничего необычного – как будет показано далее, объект-функция может быть связан с несколькими именами, может сохраняться в списке и так да- лее. Кроме того, к функциям можно прикреплять различные атрибуты, определяемые пользователем, для сохранения каких-либо данных.
Что мы можем понять из этих двух пунктов? А то, что когда вы используете инструкцию def вы просто создаете объект, у которого есть имя и магический метод __call__. По этим причинам следующий код будет работать:
Рекурсивный вызов функций
Давайте так.. рекурсивный вызов или рекурсия - это когда функция может вызывать саму себя.. может мы потом подробнее поговорим про стек вызовов, но это совершенно естественно в программировании.
Вот пример получения n`ого-числа Фибоначи:
❗️Обратите внимание
С помощью рекурсии очень удобно обрабатывать древовидные структуры(
HTML,Дерево директорий...)