Функции
Мы зачастую хотим делить нашу программу на составные блоки, это могут быть модули/пакеты модулей
, классы
для написания программ в парадигме ООП
. Одним из составных блоков нашей программы может быть функция.
Если говорить просто, то функция – это средство, позволяющее группировать наборы инструкций так, что в программе они могут запускаться неоднократно. Функции могут вычислять некоторый результат и позволять указывать вход- ные параметры, отличающиеся по своим значениям от вызова к вызову. Воз- можность оформления операций в виде функций – это очень удобный инстру- мент, который мы можем использовать в самых разных ситуациях.
Для объявления функций используется инструкция 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
,Дерево директорий
...)