В статье знакомим с функциями в Python: определение и их преимущества, создание и вызов, типы аргументов, объем переменных с подробными примерами.
Многие начинающие программисты изучают программирование только как какую-то науку, но и не догадываются, что существует даже целая философия программирования.
Один из тезисов этой философии звучит «Don’t repeat yourself», что дословно переводится как «Не повторяйся». Это значит, что не стоит писать один и тот же код несколько раз.
Чтобы избежать этого в языке программирования Python предусмотрена конструкция функций. Разберемся с ней с теоретической точки зрения и рассмотрим ряд примеров.
- Что такое функция в Python
- Создание и работа с функциями Python
- Создание
- Вызов функции Python
- Пример реализации функции на языке python
- Lambda функции
- Оператор возврата return
- Аргументы функции Python
- Обязательные (позиционные) аргументы
- Ключевые аргументы
- Преимущества ключевых аргументов в функциях
- Аргументы по умолчанию
- Аргументы переменной длины
Что такое функция в Python
Для новичков порой кажется, что это что-то новое, чем они еще ни разу не пользовались. На удивление, это неправда. С конструкцией пользователи сталкиваются каждый день.
Например, чтобы вывести текст разработчик использует print(), где в скобках указывает нужный текст. С помощью input() программист, наоборот, считывает, значения из консоли. Или, например, pow() считывает два числа: число и показатель степени, а после возвращает результат возведения в степень.
Функция Python – это блок кода, который принимает пользовательские значения, проводит некоторые операции, а после возвращает (или сразу выводит) результат выполнения этих операций.
Однако, до этого вы только пользовались встроенными function (так, кстати, называется такая конструкция в самом языке), которые подключались вместе с разными модулями и библиотеками. Помимо них есть и пользовательские функции. В них разработчик сам решает, какие аргументы будут приниматься, какие операции проводиться и что пользователь получит на выходе.
Зачем же использовать пользовательские наработки, если можно вписать код прямо в основном блоке.
На это есть несколько причин:
- Без них невозможно избежать повторения одного и того же кода. Допустим, вы разрабатываете систему авторизации и регистрации. В таком случае вам понадобится как минимум два раза вызвать функцию, которая шифрует введенный пароль. Если отказаться от этого, тогда придется дважды прописывать цикл для работы с каждым символом (представим, что используются старые методы шифрования), а после дважды понадобится создавать ключ для шифрования и так далее. В случае с функцией, достаточно было бы два раза вызвать ее, но с разными параметрами. Код сократится, как минимум, на десяток строчек.
- Гибкость. Программист вправе один раз прописать алгоритм выполнения нужных операций и вычислений, а после обращаться к этому алгоритму, но уже с разными значениями.
- Их легко модифицировать. Допустим, нужно изменить алгоритм шифрования введённого пароля. Для этого достаточно изменить сам алгоритм внутри блока. Все обращения к функции дальше будут следовать уже другому алгоритму.
- Легко импортируются в другие проекты. Если вы создаете одно большое приложение, то одним файлом с кодом не обойтись. Например, если необходима работа с сервером, то все алгоритмы отправки и принятия запросов лучше закинуть в отдельный файл с расширением .py, а после импортировать этот файл в основной проект.
Да, есть множество аргументов за использование этой конструкции и ни одного против. Выбор очевиден. А еще игнорирование функционального программирования – это плохой тон.
Допустим, ваш код посмотрит другой специалист. Что он поймет среди циклов, условий, непонятных вычислений?
А вот, например, вызов function factorial не нужно даже объяснять. Все просто: здесь происходит вычисление факториала.
Кстати, идеальная функция не должна работать с вводом и выводом, а только производить вычисления с готовыми данными.
Создание и работа с функциями Python
Итак, когда сама философия использования конструкций понятна, осталось разобраться с технической реализацией. Не беспокойтесь, после циклов и условий (которые следует изучить изначально) эта тема покажется вам до предела простой, особенно в Python.
Создание
В Python существует только один способ создания функции. Чтобы сделать это необходимо почти в начале (после импорта разных модулей и перед основным кодом) ввести следующую конструкцию:
def functionname(arguments, arguments_again): # Можно указать и один аргумент, в примере просто указан способ их перечисления
#code
x = arguments + arguments_again
return x
Разобрались? Вряд ли, если вы новичок. Рассмотрим все это дословно.
- Def в python – это ключевое слово, которое используется для указания интерпретатору, что здесь начинается функция.
- Functionname – это название, которое пользователь выберет сам. То есть functionname, как и переменная, может иметь любое название, только оно должно соответствовать правилам названия переменных (напомним, с цифры не начинать, специальные символы лучше не использовать, пробелы в названии не ставить, только латинские буквы).
- (Arguments, arguments_again) – в этой части кода передаются аргументы. Проще говоря это переменные, с которыми нужно производить вычисления.
Учтите, что отправляется значение, а не ссылка на область памяти с переменной. То есть, если изменить переменную внутри, то вне блока она не изменится (это исправляется с помощью ключевого слова global, но это уже другая тема). Чтобы перечислить несколько аргументов, нужно разделить их знаком запятой.
Под обобщающим комментарием #code мы подразумеваем все операции, происходящие внутри. Это может быть сложение (x = y + z), вычитание (x = y — z), умножение, деления, вызов других команд и так далее.
Примечательно, что все операторы должны начинаться с отступа (4 пробела или один таб). Также не стоит смешивать пробелы и табы. И, наконец, ключевое слово return, которое возвращает значение в основной код. Оно также должно начинаться с отступа.
После ключевого слова указывается переменная, которую необходимо вывести. Эта переменная должна быть создана в самой функции Python. Так как в примере выше использовалась переменная x, ее и вернем в функцию. В общем все, так и выглядит функция.
Лайфхак: если необходимо вернуть несколько переменных, то их нужно поместить в список и вернуть его. Другого нормального способа вернуть несколько переменных не существует.
Вызов функции Python
Теперь, когда тело функции готово, надо разобраться, как вызвать функцию в python.
Работает это примерно также, как и с переменной, необходимо указать ее имя, а также выбрать, что необходимо сделать с полученным результатом. Однако не забывайте, что большинство функций запрашивают у разработчика определенные аргументы. В случае, если их не передать, произойдет фатальная ошибка.
Итак, попробуем вызвать функцию, созданную в предыдущем подразделе, а полученное значение запишем в переменную answer. Делается это всего в одну строчку (плюс еще одна для проверки результата):
answer = functionname(5, 3) # Передаем в функцию два значения: 5 и 3
print(answer) # Выводим результат
Не забудьте, что выше нужно добавить кусок кода с самой функцией, иначе ничего не будет работать. В качестве ответа пользователь получит цифру 8.
А теперь, чтобы подчеркнуть лаконичность этого метода, модифицируем код так, чтобы он принимал разные значения в функцию и выводил результат:
print(functionname(2, 4))
print(functionname(3, 10))
print(functionname(-1,1))
print(functionname(0,0))
Теперь посмотрим на результат:
Для практики попробуйте создать еще несколько строк с разными значениями.
Пример реализации функции на языке python
Если вы не разобрались в теории выше, то это не беда. Скорее всего на практических примерах все станет куда более понятным.
Допустим, необходимо реализовать функцию, которая принимает два разных значения в две переменные, а после находит самое большее из них. От слов к делу:
def max(x, y): # create function in python language
if(x > y): # если x больше y
return x # вывести x
else: # иначе
return y # вывести y
x = int(input("Введите x:")) # Запрашиваем нужное значение и переводим его в числовой тип int
y = int(input("Введите y:"))
print("Наибольшее из двух чисел:", max(x,y)) # сразу выводим результат в консоль
Готово. Смотрим результат:
Другой пример: функция, которая будет находить среднеарифметическое всех чисел в передаваемом списке.
Чтобы сделать это, необходимо знать цикл for, а также функцию len. Впрочем, в нашем случае можете просто переписать код и попытаться разобраться в нем. Код:
def rate(all_numbers):
summa = 0;
for i in all_numbers: # перебор всех элементов
summa += i
answer = summa / len(all_numbers)
return round(answer,2) # округление до двух знаков после запятой
all_rates = [4, 6, 2, 6, 2, 8, 4]
print(rate(all_rates))
Надеемся, что двух примеров достаточно для понимания сути.
Чтобы закрепить навык, предлагаем создать функции для следующих задач:
- Поиск наименьшего значения в передаваемом списке.
- Возвращение модуля введенного числа. Модуль всегда положительный.
- Нахождение суммы всех делителей введенного числа (задача повышенной сложности).
Lambda функции
Довольно часто возникает необходимость создать одноразовую функцию, которая принимает какие-то аргументы, а после возвращает какой-то результат. Чтобы не сильно усложнять с объявлением ключевого слова def, скобками, return и так далее, можно использовать конструкцию анонимных Lambda функций.
Базовый синтатаксис выглядит следующим образом:
lambda arguments: expression
Теперь по порядку:
- Lambda – это ключевое слово для объявления функции.
- Arguments – это аргументы, которые передаются в функцию. Чтобы передать несколько аргументов, нужно указать их через запятую.
- Expression – это код, который нужно выполнить. Учтите, нужно выполнить только одну операцию, результат которой сразу вернется в качестве return.
Итак, рассмотрим пример использования Lambda. Необходимо создать функцию, которая делила бы годовой бюджет на 12 месяцев, а после округляло его до одного знака после запятой. Решение:
Пока вы вряд ли понимаете, зачем можно использовать эту структуру. В будущем, при работе с map, она вам особенно пригодится.
Оператор возврата return
Выше мы уже не раз использовали оператор возврата return в python. Его единственная задача – это возвращать в основной код переменные из функции.
-Зачем это нужно, разве нельзя обратиться к новой переменной сразу?
Ответ – нет, нельзя.
Дело в том, что переменные в Python могут быть либо локальными, либо глобальными. По умолчанию они все локальные.
Так вот, локальные переменные существуют только в пределах одного блока. То есть, все операции внутри функции недоступны из вне, и наоборот, все переменные в основном коде нельзя неявно передать в функцию. Это удобно, ведь таким образом не получится случайно изменить какую-то важную переменную.
По итогу, аргументы используются для введения переменных в функцию, а return для вывода значения из этой функции. Примечательно, что вывести можно только одну переменную.
Появление return в коде обозначает завершение функции, вне зависимости от наличия дальнейших инструкций.
Пример:
def test():
print("Строка 1")
print("Строка 2")
return
print("Строка 3")
test()
При выполнении этого кода выведется только «Строка 1» и «Строка 2». «Строка 3» появляется после return, а потому не выводится.
Заметьте, что функция может не принимать аргументов (пустые скобки), а return и вовсе может ничего не возвращать. В коде может быть несколько return-ов одновременно.
Аргументы функции Python
Только недавно мы упомянули, что аргументы – это основной способ передачи переменных. Так как их важность невозможно переоценить, разработчики позаботились о том, чтобы аргументы можно было гибко настроить.
Обязательные (позиционные) аргументы
Выше мы познакомились именно с ними. Обязательные аргументы не могут быть пропущены при вызове.
Например, у функции для поиска возведения в степень должен быть обязательный аргумент с числом, которое нужно возвести в степень. Чтобы задать позиционный аргумент, достаточно указать его в скобках.
Чтобы записать значение именно в этот аргумент, нужно ввести его в той же позиции при вызове функции. Если мы указываем два аргумента (x,y), то при вызове функции мы должны сперва указать значение для x, а потом для y.
Ключевые аргументы
Согласитесь, передавать значения в той последовательности, в которой они указаны в аргументах проблематично.
Допустим, необходимо обратиться к внешнему коду. Тогда разработчик будет вынужден открыть этот код и посмотреть, в каком порядке там идут аргументы. Чтобы избежать таких проблем, достаточно использовать ключевые аргументы.
В теле функции они никак не изменяются, а вот при вызове вместо простого значения указывается связка «название_аргумента=значение».
Пример:
def ranger(min, max):
ranger_list = range(min, max + 1)
return ranger_list
d = ranger(min = 4, max = 8) # это работает
d = ranger(max = 8, min = 4) # и это работает
d = ranger(4, 8) # позиционная передача, работает
d = ranger(8,4) # по сути работает, но только значения передались не в те аргументы
Особенно полезно, когда аргументов много и сохранить эту последовательность при передаче данных сложно.
Преимущества ключевых аргументов в функциях
Существует ряд причин использовать ключевые аргументы Python:
- Так разработчик точно отследит куда попали переданные данные.
- Это необходимо при добавлении необязательных аргументов.
- Это более понятно для других разработчиков (даже в примере выше min = 4 более понятно, чем просто 4).
Однако, не стоит злоупотреблять такой возможностью. Если у вас функция, которой нужен только один аргумент, зачем захламлять код его постоянным упоминанием.
Аргументы по умолчанию
Возможны ситуации, когда одному из аргументов нужно задавать значение по умолчанию, которое сохранится, если разработчик не передаст в качестве аргумента другое значение.
В теории не совсем понятно, но давайте рассмотрим небольшой пример. Вспомним базовый курс физики, а именно формулу силы тяжести: F = mg. Сделаем функцию, которая на основе введенных m и g будет вычислять значение.
Однако, скажите вы, g – это же константа, приблизительно равная 9.8. Да, но только на нашей планете. При желании разработчик может указать собственное g.
Решение:
def f(m, g = 9.8):
return m * g
print("F =", f(10), "H") # не указываем аргумент со значением по умолчанию
print("F =", f(10, 2.1), "H") # указываем аргумент со значением по умолчанию
Результат:
Вывод с и без использования значения по умолчанию
Аргументы переменной длины
Все вышеперечисленные аргументы принимают только одну переменную. Но что, если разработчик не знает точно, сколько переменных будет отправлено на обработку. Не удивляйтесь, такое возникает чаще, чем кажется.
Представим, что нам нужна функция, которая делает связку координат. Отправить в нее можно бесконечное множество координат. В дальнейшем такое можно использовать для создания многоугольников.
Чтобы передать неизвестное множество аргументов, достаточно перед началом названия аргумента указать значок звездочки «*». Теперь все переменные поместятся в этот аргумент в виде списка.
Попробуем решить задачу с формированием координат:
def figure(*args): # Указываем аргумент переменной длины
i = 0 # счетчик для цикла
string_coords = "" # строка, куда будет записан итоговый текст
while (i < len(args)):
if(i % 2 == 0): # распределение на координаты абсцисс(четная) и ордината(нечетная)
string_coords += "x(" + str(args[i]) + ", " # склеивание строки
else:
string_coords += str(args[i]) + ")"
i += 1 # увеличение счетчика
return string_coords
print(figure(3,5,1,5,7,4,2,2)) # передача нескольких значений
Смотрим результат ниже.
Даже если темы не поддаются с первого раза, то не стоить забрасывать их изучение. С ними часто сталкиваются на форумах, в учебниках, даже при работе в команде участнику лучше редактировать отдельный модуль, нежели основной код. Постепенно, учась на своих ошибках и применяя их на практике, вы запомните все функции и начнете использовать их уже на автомате.