В программировании функция представляет собой выделенный блок кода, доступ к которому можно получить через его имя. При вызове выполняются команды, определенные в теле функции.
Функции можно воспринимать как небольшие программные модули, которые сами по себе не исполняются, а интегрируются в основную программу. Их также называют подпрограммами. Функции, при необходимости, могут принимать и возвращать данные, но обычно они получают их не через ввод с клавиатуры или файла, а из программы, которая их вызывает, и также возвращают туда результаты своей работы.
В языках программирования, таких как Python, существует множество встроенных функций. Мы уже знакомы с такими, как print(), input(), int(), float(), str(), type(). Код их реализации скрыт внутри языка, и мы взаимодействуем с ними через их имена—интерфейсы функций.
Программисты могут создавать пользовательские функции, то есть те, которые пишутся ими самими. В данном контексте "пользователь" обозначает разработчика. Давайте разберемся, зачем нужны пользовательские функции и как их можно создавать.
Предположим, требуется трижды ввести пары чисел и посчитать их сумму. Это можно сделать, используя цикл:
i = 0 while i < 3: a = int(input()) b = int(input()) print(a+b) i += 1
Но, если перед вводом каждой пары чисел нужно выводить сообщение с пояснением цели чисел, причём это сообщение будет меняться каждый раз, цикл прервать нельзя. Это превратится в длинный код с повторяющимися блоками в разных местах:
print("Сколько бананов и ананасов для обезьян?") a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько жуков и червей для ежей?") a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько рыб и моллюсков для выдр?") a = int(input()) b = int(input()) print("Всего", a+b, "шт.")
Как это будет выглядеть на практике:
Сколько бананов и ананасов для обезьян? 15 5 Всего 20 шт. Сколько жуков и червей для ежей? 50 12 Всего 62 шт. Сколько рыб и моллюсков для выдр? 16 8 Всего 24 шт.
Использование функций позволяет избежать повторения кода в программе. С их помощью можно вызывать один и тот же фрагмент кода лишь по мере необходимости.
Определение функции. Оператор def
В Python функции определяются с помощью ключевого слова def. Вот пример:
def countFood(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.")
Это демонстрация того, как определить функцию. Подобно условным операторам и циклам, функция содержит заголовок и тело, где заголовок заканчивается двоеточием и переносится на новую строку, а тело выделено отступом.
Ключевое слово def сообщает интерпретатору, что начинается определение функции. За ним следуют имя функции и круглые скобки. В примере они пустые, что означает, что функция не принимает данных при вызове. Однако туда можно добавить параметры, если функция должна их принимать.
После заголовка идет тело функции с инструкциями, которые выполняются при её вызове. Важно отличать определение функции от её вызова. Они могут находиться в разных частях кода. Можно определить функцию, но ни разу её не вызвать, но нельзя вызывать функцию, которая ещё не определена.
Вызов функции
Рассмотрим программу с определённой функцией:
def countFood(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько бананов и ананасов для обезьян?") countFood() print("Сколько жуков и червей для ежей?") countFood() print("Сколько рыб и моллюсков для выдр?") countFood()
После каждого информационного сообщения функция вызывается, просто указывая её имя со скобками, в которых в нашем примере ничего нет. В данном коде вызывается трижды.
При вызове функции, выполнение программы переключается на её определение и исполняет команды её тела. После выполнения тело функции возвращается к месту вызова, продолжая выполнение расположенного там кода.
В Python определение функции должно находиться перед её вызовом, так как интерпретатор обрабатывает код построчно и он ещё не знает о функции, если её определение находится ниже в коде. Если вызвать функцию перед её определением, выдаётся ошибка NameError:
print("Сколько бананов и ананасов для обезьян?") countFood() print("Сколько жуков и червей для ежей?") countFood() print("Сколько рыб и моллюсков для выдр?") countFood() def countFood(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.")
Результат:
Сколько бананов и ананасов для обезьян? Traceback (most recent call last): File "test.py", line 2, in <module> countFood() NameError: name 'countFood' is not defined
В некоторых компилируемых языках порядок определения функций и их вызова не имеет значение, но для удобства кода программисты всё равно соблюдают определённые правила.
Функции придают программе структуру
Функции полезны не только возобновляемым использованием одного и того же кода из разных точек программы. Они придают коду ясную структуру. Функции помогают разбить программу на логические части, каждая из которых выполняет конкретную задачу.
Например, нужно написать программу, вычисляющую площади фигур. Пользователь выбирает, какую фигуру хочет рассчитать, а после вводит исходные данные. Для разветвления потока выполнения используется оператор if-elif-else:
figure = input("1-прямоугольник, 2-треугольник, 3-круг: ") if figure == '1': a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a*b)) elif figure == '2': a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) elif figure == '3': r = float(input("Радиус: ")) print("Площадь: %.2f" % (3.14 * r**2)) else: print("Ошибка ввода")
Этот код работает, но рассмотрим вариант с функциями:
def rectangle(): a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a*b)) def triangle(): a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) def circle(): r = float(input("Радиус: ")) print("Площадь: %.2f" % (3.14 * r**2)) figure = input("1-прямоугольник, 2-треугольник, 3-круг: ") if figure == '1': rectangle() elif figure == '2': triangle() elif figure == '3': circle() else: print("Ошибка ввода")
На первый взгляд программа может показаться сложнее, так как каждая из функций вызывается только один раз, но фактически они делают код более структурированным. Основная логика программы теперь состоит из отдельных блоков, которые можно использовать, как управляемые модули.
Если нужно изменить алгоритм расчета площади треугольника, не нужно искать код по всей программе. Достаточно просмотреть все объявления функций и изменить код в теле одной из них.
Функции также можно использовать в других программах. Просто импортируйте их из текущего файла с помощью специальных инструментов Python.
Практическая работа
Функции можно вызывать из других функций. Реализуйте программу по следующему описанию.
Основная ветка программы содержит одну строку, вызывающую функцию test(). Она запрашивает ввод целого числа. Если число положительное, вызывается функция positive(), которая выводит "Положительное". Если число отрицательное, вызывается функция negative(), которая выводит "Отрицательное".
Важно, что вызов test() должен быть прописан после всех определений функций. А порядок, в котором они определяются, имеет ли он значение? Могут ли positive() и negative() быть объявлены после функции test()? Проверьте это перемещением объявлений. Проанализируйте результат.