# Функции
Функция — блок кода для выполнения определенной задачи, который можно использовать многократно в разных частях программы. Существует множество встроенных в Python готовых функций. Некоторые вы уже применяли ранее: print() , str() , int() , float() , len() .
Создание функции называется определение. Оно начинается с ключевого слова def (от англ. definition, «определение»), затем идут имя функции, её аргументы, или параметры в круглых скобках и двоеточие. Начиная со следующей строки, с отступом в 4 пробела от начала, записывают тело функции — код, который она выполняет. Обращение к функции называется вызов функции. Функция вызывается по имени, при вызове ей передают аргументы, с которыми она должна что-то сделать.
Напишем приветствие как функцию:
# код функции say_hello def say_hello(current_hour): if current_hour 5 or current_hour >= 23: print('Доброй ночи!') elif current_hour >= 6 and current_hour 11: print('Доброе утро!') elif current_hour >= 12 and current_hour 17: print('Добрый день!') elif current_hour >= 18 and current_hour 22: print('Добрый вечер!') # основной код say_hello(4) # вызов функции с аргументом 4 print('------') say_hello(10) # вызов функции с аргументом 10 print('------') say_hello(15) # ещё один вызов функции print('------') say_hello(20) # и ещё один вызов функции
Доброй ночи! ------ Доброе утро! ------ Добрый день! ------ Добрый вечер!
Создали функцию с именем say_hello (англ. say hello, «поздороваться»). В любом месте программы при вызове say_hello() будет выводиться на экран приветствие с текстом, зависящим от аргумента current_hour (англ. current hour , «текущий час»).
# Упражнения
- На основе заготовленного кода напишите функцию print_friends_count() для вывода количества друзей. Аргументом сделайте friends_count . Вызовите эту функцию не менее трёх раз с разными аргументами. Значениями friends_count могут быть любые натуральные числа.
def print_friends_count(friends_count): if friends_count == 1: print('У тебя 1 друг') elif 2 friends_count 4: print('У тебя ' + str(friends_count) + ' друга') elif friends_count >= 5: print('У тебя ' + str(friends_count) + ' друзей')
- Напишите цикл для запусков print_friends_count() c аргументами от 1 до 10. Проследите изменения выведенных надписей.
# Упражнения tkinter
- Напишите оконное приложение выводящее список количества друзей.
- Напишите оконное приложение с полем ввода количества друзей. Кнопкой при нажатии на которую выводится сообщение о количестве друзей.
# Аргументы функции
В Python аргументам функций может быть присвоено значение по умолчанию. Оно подставляется, когда при вызове функции вы не оставляете насчёт аргументов никаких инструкций.
# код функции say_hello def say_hello(current_hour, name=''): if current_hour 5 or current_hour >= 23: hello_message = 'Доброй ночи' elif current_hour >= 6 and current_hour 11: hello_message = 'Доброе утро' elif current_hour >= 12 and current_hour 17: hello_message = 'Добрый день' elif current_hour >= 18 and current_hour 22: hello_message = 'Добрый вечер' if name != '': print(hello_message + ', ' + name + '!') else: print(hello_message + '!') # основной код say_hello(10, 'Тимур') print('------') say_hello(14, 'Елена') print('------') say_hello(20)
Доброе утро, Тимур! ------ Добрый день, Елена! ------ Добрый вечер!
Функция say_hello() принимает два аргумента — current_hour и name (англ. name, «имя»), которому задано значение по умолчанию. При вызове только с одним аргументом current_hour значением второго аргумента name станет пустая строка.
При вызове функции можно явно указывать, какому аргументу какое значение соответствует. В таком случае порядок следования аргументов в скобках роли не играет.
say_hello(current_hour=10, name='Тимур') print('------') say_hello(name='Елена', current_hour=14) print('------') say_hello(current_hour=20)
Доброе утро, Тимур! ------ Добрый день, Елена! ------ Добрый вечер!
# Упражнения
- Допишите код функции print_friends_count() , добавьте аргумент name со значением по умолчанию. Если вы при вызове передаёте функции имя, она должна вывести на экран строку вида ‘, у тебя N друзей’ , если нет — тогда просто ‘У тебя N друзей’ .
- Анфиса может анализировать списки. Например, подсчитывать дни, когда в вашем городе или в городах ваших друзей стояла хорошая погода.
Есть списки средних дневных температур в Москве за май 2017 и 2018 годов. Создайте функцию comfort_count(temperatures) для подсчёта в переданном списке комфортных дней — дней с температурой воздуха от 22 до 26 градусов включительно.
Функция в результате работы должна вывести на экран строку ‘Количество комфортных дней в этом месяце: N’ , где N — результат подсчёта в цикле с условием. Сначала посчитайте приятные дни в мае 2017-го года, а потом — в мае 2018-го.
may_2017 = [24, 26, 15, 10, 15, 19, 10, 1, 4, 7, 7, 7, 12, 14, 17, 8, 9, 19, 21, 22, 11, 15, 19, 23, 15, 21, 16, 13, 25, 17, 19] may_2018 = [20, 27, 23, 18, 24, 16, 20, 24, 18, 15, 19, 25, 24, 26, 19, 24, 25, 21, 17, 11, 20, 21, 22, 23, 18, 20, 23, 18, 22, 23, 11] # допишите код ниже
# Разбиение на функции
В больших проектах, написанных на Python, принято выносить весь повторяющийся код в отдельные функции перед телом основной программы. Посмотрим на пример:
# код функции say_hello def say_hello(current_hour): if current_hour 5 or current_hour >= 23: print('Доброй ночи!') elif current_hour >= 6 and current_hour 11: print('Доброе утро!') elif current_hour >= 12 and current_hour 17: print('Добрый день!') elif current_hour >= 18 and current_hour 22: print('Добрый вечер!') # перенесли основной код внутрь функции runner() def runner(): say_hello(4) say_hello(10) say_hello(15) say_hello(20) # в теле программы остаётся только один вызов: runner()
Функция say_hello() содержит основную логику, а runner() (от англ. run, «запускать») выполняет роль управляющего механизма. Такое разделение придаёт коду программы аккуратный внешний вид, делает его более выразительным, упрощает чтение.
# Упражнения
- Подготовьте код Виты к использованию на сервере.
- Напишите функцию process_query() (англ. process query, «обработать запрос»). Перенесите в неё весь код из тела основной программы. Эта функция будет принимать на вход запросы пользователя и выдавать ответ на них. Пока она может обработать всего один запрос — сообщить количество друзей.
- Добавьте вызов функции process_query() в тело основной программы.
FRIENDS = ['Серёга', 'Соня', 'Дима', 'Алина', 'Егор'] def print_friends_count(friends_count): if friends_count == 1: print('У тебя 1 друг') elif 2 friends_count 4: print('У тебя ' + str(friends_count) + ' друга') elif friends_count >= 5: print('У тебя ' + str(friends_count) + ' друзей') # перенесите в функцию process_query() вот этот код: print("Привет, я Анфиса!") count = len(FRIENDS) print_friends_count(count)
- На серверы приходит множество запросов — от разных пользователей или от других серверов. Измените функцию process_query() (обработчик запроса), чтобы она поддерживала несколько разных запросов, а не только один.
- Добавьте аргумент query в функцию process_query() . Этот аргумент будет сообщать, какой именно запрос необходимо обработать.
- В начало функции process_query() добавьте проверку значения переменной query: если значение равно ‘Сколько у меня друзей?’ — выведите ответ на этот вопрос, как в предыдущем задании;
- в противном случае — выведите ». Добавьте вызов process_query(‘Сколько у меня друзей?’) в основное тело программы. Добавьте ещё один вызов process_query(‘Как меня зовут?’) в основное тело программы.
- Доработайте программу.
- Добавьте в функцию process_query() обработку ещё одного запроса ‘Кто все мои друзья?’. В ответ нужно выводить на экран Твои друзья: , где — строка, состоящая из списка друзей, разделённых запятой и пробелом.
- Добавьте вызов process_query(‘Кто все мои друзья?’) в тело основной программы.
# Возврат значений из функции
Пока что все наши функции печатали результаты своей работы на экран. Но обычно задача функции не сводится к выступлениям в печати. Как правило, это код, производящий специальные вычисления. Он не выводит результаты на экран, а возвращает их как значения. Значение вернётся в вызывающий код, и там будет использовано. Например, сохранено в переменной. Если программе нужно, к примеру, несколько раз посчитать одно и то же, эти вычисления поручают особым функциям:
# функция для вычисления периметра прямоугольника # от англ. calculate, "вычислять" def calc_perimeter(side_a, side_b): return (side_a + side_b) * 2 # функция для вычисления площади прямоугольника def calc_square(side_a, side_b): return side_a * side_b # Посчитаем периметр и площадь прямоугольника со сторонами 8 и 10 метров a = 8 b = 10 p = calc_perimeter(a, b) s = calc_square(a, b) print('Периметр прямоугольника равен ' + str(p) + ' м.') print('Площадь прямоугольника равна ' + str(s) + ' кв. м.') # можем произвести расчёты и для другого прямоугольника p = calc_perimeter(3, 4) print('Периметр прямоугольника равен ' + str(p) + ' м.') # Возвращённое значение не обязательно сохранять в переменной. # Можно сразу вывести на экран: print('Площадь прямоугольника равна ' + str(calc_square(3, 4)) + ' кв. м.')
Периметр прямоугольника равен 36 м. Площадь прямоугольника равна 80 кв.м. Периметр прямоугольника равен 14 м. Площадь прямоугольника равна 12 кв.м.
Ключевое слово return (англ. «возвращать») указывает, какое значение функция вернёт основному коду.
# Упражнения
- Доработаем программу подсчёта комфортных дней в мае.
- Измените функцию comfort_count() , чтобы она не печатала количество комфортных дней, а возвращала.
- Чтобы увидеть результат выполнения функции, напечатайте его в основном коде командой print(comfort_count(may_2017)) .
may_2018 = [20, 27, 23, 18, 24, 16, 20, 24, 18, 15, 19, 25, 24, 26, 19, 24, 25, 21, 17, 11, 20, 21, 22, 23, 18, 20, 23, 18, 22, 23, 11] may_2017 = [24, 26, 15, 10, 15, 19, 10, 1, 4, 7, 7, 7, 12, 14, 17, 8, 9, 19, 21, 22, 11, 15, 19, 23, 15, 21, 16, 13, 25, 17, 19] # в этой функции не должно быть вызова print def comfort_count(temperatures): count = 0 for temp in temperatures: if 22 temp 26: count += 1 return count print(comfort_count(may_2017)) # здесь нужна команда печатать результат, возвращённый функцией comfort_count()
# Вызов функции из функции
Функцию можно вызвать не только из основного кода, но и из другой функции.
# это первая функция, она только возвращает значение # выражение \n означает перевод строки def Jack(): return 'в доме, который построил Джек.\n' # это вторая функция, она вызывает первую # и возвращает свою строку вместе с результатом функции Jack() def wheat(): return 'которая в тёмном чулане хранится\n' + Jack() # а это третья функция, которая вызывает вторую, # которая вызывает первую def bird(): return 'которая часто ворует пшеницу,\n' + wheat() print('Вот дом, который построил Джек.\n') print('А это пшеница, ' + wheat()) print('А это весёлая птица-синица, ' + bird())
Вот дом, который построил Джек. А это пшеница, которая в тёмном чулане хранится в доме, который построил Джек. А это весёлая птица-синица, которая часто ворует пшеницу, которая в тёмном чулане хранится в доме, который построил Джек.
Хорошая привычка — выделять вычисления и вывод в отдельные функции, чтобы печать результатов не была разбросана по всему коду.
# здесь вычисления периметра и площади прямоугольника def calc_perimeter(side_a, side_b): return (side_a + side_b) * 2 def calc_square(side_a, side_b): return side_a * side_b # здесь подготовка результата def show_info(side_a, side_b): p = calc_perimeter(side_a, side_b) s = calc_square(side_a, side_b) text = 'Периметр равен ' + str(p) + ' м., ' text += 'а площадь - ' + str(s) + ' кв.м.' return text # здесь все вызовы print() def runner(): print(show_info(8, 10)) print(show_info(3, 4)) runner()
Периметр равен 36 м., а площадь - 80 кв.м. Периметр равен 14 м., а площадь - 12 кв.м.
Если бы мы ошиблись и забыли вернуть строку text из функции show_info(), то вывод получился бы странный:
# здесь подготовка результата def show_info(side_a, side_b): p = calc_perimeter(side_a, side_b) s = calc_square(side_a, side_b) text = 'Периметр равен ' + str(p) + ' м., ' text += 'а площадь - ' + str(s) + ' кв.м.' # здесь все вызовы print() def runner(): print(show_info(8, 10)) print(show_info(3, 4))
Что такое None здесь? Это специальное значение в Python, и оно обозначает. ничего (англ. none, «ничто»). Если значение какой-нибудь переменной равно None , обычно это значит, что она не определена, не имеет никакого значения. Функция runner() печатает результаты вызовов функции show_info() . Так как в ней нет return , то она ничего не возвращает, и print() печатает это самое ничего.
# Упражнения
- Измените код Виты. Оставьте вывод на экран, т.е. вызовы функции print() , только в одном месте — в основном теле программы. Эти вызовы уже написаны в предварительном коде задания. Все прошлые выводы на экран — в функциях show_count_friends() и process_query() — замените на возвращения результатов из функции оператором return .