Функции
Функция
— блок кода для выполнения определенной задачи, который можно использовать многократно в разных частях программы. Существует множество встроенных в 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) # и ещё один вызов функции
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Доброй ночи!
------
Доброе утро!
------
Добрый день!
------
Добрый вечер!
2
3
4
5
6
7
Создали функцию с именем 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) + ' друзей')
2
3
4
5
6
7
- Напишите цикл для запусков
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)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Доброе утро, Тимур!
------
Добрый день, Елена!
------
Добрый вечер!
2
3
4
5
Функция 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)
2
3
4
5
Доброе утро, Тимур!
------
Добрый день, Елена!
------
Добрый вечер!
2
3
4
5
Упражнения
Допишите код функции
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]
# допишите код ниже
2
3
4
Разбиение на функции
В больших проектах, написанных на 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()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Функция 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)
2
3
4
5
6
7
8
9
10
11
12
13
14
- На серверы приходит множество запросов — от разных пользователей или от других серверов. Измените функцию
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)) + ' кв. м.')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Периметр прямоугольника равен 36 м.
Площадь прямоугольника равна 80 кв.м.
Периметр прямоугольника равен 14 м.
Площадь прямоугольника равна 12 кв.м.
2
3
4
Ключевое слово 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()
2
3
4
5
6
7
8
9
10
11
12
13
14
Вызов функции из функции
Функцию можно вызвать не только из основного кода, но и из другой функции.
# это первая функция, она только возвращает значение
# выражение \n означает перевод строки
def Jack():
return 'в доме, который построил Джек.\n'
# это вторая функция, она вызывает первую
# и возвращает свою строку вместе с результатом функции Jack()
def wheat():
return 'которая в тёмном чулане хранится\n' + Jack()
# а это третья функция, которая вызывает вторую,
# которая вызывает первую
def bird():
return 'которая часто ворует пшеницу,\n' + wheat()
print('Вот дом, который построил Джек.\n')
print('А это пшеница, ' + wheat())
print('А это весёлая птица-синица, ' + bird())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Вот дом, который построил Джек.
А это пшеница, которая в тёмном чулане хранится
в доме, который построил Джек.
А это весёлая птица-синица, которая часто ворует пшеницу,
которая в тёмном чулане хранится
в доме, который построил Джек.
2
3
4
5
6
7
8
Хорошая привычка — выделять вычисления и вывод в отдельные функции, чтобы печать результатов не была разбросана по всему коду.
# здесь вычисления периметра и площади прямоугольника
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()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Периметр равен 36 м., а площадь - 80 кв.м.
Периметр равен 14 м., а площадь - 12 кв.м.
2
Если бы мы ошиблись и забыли вернуть строку 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))
2
3
4
5
6
7
8
9
10
11
None
None
2
Что такое None здесь? Это специальное значение в Python, и оно обозначает... ничего (англ. none, "ничто"). Если значение какой-нибудь переменной равно None
, обычно это значит, что она не определена, не имеет никакого значения. Функция runner()
печатает результаты вызовов функции show_info()
. Так как в ней нет return
, то она ничего не возвращает, и print()
печатает это самое ничего.
Упражнения
- Измените код Виты. Оставьте вывод на экран, т.е. вызовы функции
print()
, только в одном месте — в основном теле программы. Эти вызовы уже написаны в предварительном коде задания. Все прошлые выводы на экран — в функцияхshow_count_friends()
иprocess_query()
— замените на возвращения результатов из функции операторомreturn
.