Функции в Python
Вы
уже применяли встроенные функции Python и писали собственные. Перед
тем, как погрузиться в более серьёзное их изучение — стоит освежить в
памяти всё, что о них уже известно.
Функции: краткое досье
Функция
в программировании — это именованный фрагмент кода, предназначенный для
многократного использования. Функцию можно вызывать (запускать её код)
из любого места программы; вызывать функцию можно сколько угодно раз.
Функции бывают встроенные,
они написаны разработчиками Python или авторами модулей. Встроенные
функции хороши тем, что не обязательно выяснять, что происходит у них
«под капотом», а можно просто взять и применить их: функция
str()
превратит данные в строку, print()
— выведет информацию в консоль, а type()
определит тип данных.Функцию можно написать самостоятельно: для этого нужно придумать ей информативное имя, объявить её и описать тело функции
— код, который будет выполняться при вызове. Тело функции отбивается
четырьмя отступами от начала строки, в которой объявлена эта функция.
Скопировать кодPYTHONdef best_function_in_this_code(): # Объявление функции
print('Других функций тут нет!') # Тело функции
best_function_in_this_code() # Вызов функции
best_function_in_this_code() # Ещё один вызов функции
# В результате двух вызовов функции будет напечатано:
# Других функций тут нет!
# Других функций тут нет!
Функции, как правило, пишут так, чтобы они
- обрабатывали какие-то входящие данные;
- возвращали какое-то значение, результат работы.
Входящие данные функция принимает в параметры — в переменные, обрабатываемые в теле функции. Параметры указываются после имени функции в скобках, через запятую.
Скопировать кодPYTHON# Параметры функции - а и b
def never_print_result(a, b):
...
Значения, передаваемые в функцию при вызове, называют аргументами функции:
Скопировать кодPYTHONdef never_print_result(a, b):
...
# Вызываем функцию с аргументами 5 и 4
never_print_result(5, 4)
Переданные в функцию значения можно обрабатывать только в теле функции, получить доступ к параметрам функции извне нельзя.
Функция обрабатывает входящие данные и получает какой-то результат. Этот результат функция может вернуть — передать для дальнейшей обработке вне этой функции.
В теле функции возвращаемое значение указывается после ключевого слова return.
После выполнения инструкции
return
функция завершит выполнение.Запустите программу. При вызове функции
never_print_result()
строка 'Я не напечатаю ...'
никогда не будет напечатана: выполнение функции будет прервано инструкцией return
КодPYTHON
8
1
def never_print_result(a, b):
2
result = a + b
3
return result
4
print(f'Я не напечатаю {result}. НИ-КОГ-ДА!')
5
6
# В переменную summa вернётся результат работы функции
7
summa = never_print_result(5, 4)
8
print(summa)
Разбиение кода на функции
Программу работы с данными из онлайн-кинотеатра можно оптимизировать, разобрав её код на функции.
Сейчас рекомендации для просмотра печатаются таким кодом:
Скопировать кодPYTHONrating = 3.0
if rating > 4.7:
print('Фильм крут')
elif rating > 3.5:
print('Смотреть можно')
else:
print('Так себе киношечка')
print('Проверка окончена')
Недостатки
этого подхода в том, что этот код находится в основном теле программы и
может быть выполнен лишь единожды. Значит, чтобы обработать следующее
значение рейтинга — нужно перезапустить программу или ещё раз написать
этот блок кода.
Перенесём код в тело функции и вместо того, чтобы печатать результат, будем возвращать его из функции. Возвращаемый результат будет записан в переменную
result
.Запустите код несколько раз, передавая в функцию разные аргументы.
КодPYTHON
12
1
def print_recommendation(rating):
2
if rating > 4.7:
3
return 'Фильм крут'
4
elif rating > 3.5:
5
return 'Смотреть можно'
6
else:
7
return 'Так себе киношечка'
8
9
10
result = print_recommendation(4.1)
11
12
print(result)
Инструкция
return
прерывает выполнение функции; за счёт этого код можно упростить и сделать более читаемым:Скопировать кодPYTHONdef print_recommendation(rating):
if rating > 4.7:
return 'Фильм крут'
if rating > 3.5:
return 'Смотреть можно'
# Если не сработало ни одно условие -
# функция вернёт это сообщение:
return 'Так себе киношечка'
result = print_recommendation(4.1)
print(result)
Такой
подход помогает избавиться от излишней вложенности условий и циклов.
Применяйте его! Кто-то из великих сказал: «Плоское лучше вложенного» — и
был прав!
Функция не обязательно должна
возвращать какие-то значения: она может выполнить какую-то работу
(например, вывести строку на печать) — и завершиться.
Скопировать кодPYTHONdef super_print(movies):
print('Подготовка к печати')
print(movies)
print('Готово!')
movies_names = ['Хакеры', 'Сеть', 'Трон', 'Матрица']
# Вызов функции не нужно передавать в переменную:
# функция ничего не вернёт, записывать в переменную нечего.
super_print(movies_names)
# Вывод в терминал:
# Подготовка к печати
# ['Хакеры', 'Сеть', 'Трон', 'Матрица']
# Готово!
Значения параметров по умолчанию
Для вызова функции необходимы все аргументы. Если пропустить хотя бы один из них — будет выдано сообщение об ошибке.
Скопировать кодPYTHONdef get_mod_diff(a, b):
"""Функция возвращает результат разницы полученных значений по модулю."""
# Функция abs вернет значение по модулю
diff = abs(a - b)
return diff
x = 3
y = 4
print(get_mod_diff(x))
# Вывод в терминал: TypeError: get_mod_diff() missing 1 required positional argument: 'b'
Чтобы
избежать такой ситуации — можно назначить значение параметра по
умолчанию: это значение будет применено, если при вызове параметр не
передан.
Скопировать кодPYTHON# При указании значения по умолчанию
# пробелы вокруг оператора в выражении b=1 не нужны. Так говорит PEP8.
def get_mod_diff(a, b=1):
"""Функция возвращает результат разницы полученных значений по модулю."""
diff = abs(a - b)
return diff
x = 3
y = 4
print(get_mod_diff(x))
# Вывод в терминал: 2
В этом случае второй аргумент при вызове функции становится необязательным (или опциональным).
Позиционные и именованные параметры
В функции
get_mod_diff()
позиции аргументов и параметров просто сопоставлены по порядку:
аргумент №1 соответствует параметру №1, аргумент №2 — параметру №2.При вызове функции можно передавать аргументы, указывая имена параметров. Порядок именованных аргументов при вызове не важен:
Скопировать кодPYTHONdef get_mod_diff(a, b=1):
"""Функция возвращает результат разницы полученных значений по модулю."""
diff = abs(a - b)
return diff
x = 3
y = 4
# Именованные аргументы можно передавать в любом порядке, функция всё поймёт и примет.
print(get_mod_diff(b=y, a=x))
Оператор «звёздочка»
Оператор
*
в Python означает не только умножение: он позволяет «распаковывать» итерируемые объекты, например — списки:Скопировать кодPYTHONx = [10, 22, 334]
y = [*x, 4, 5, 6]
print(y)
# Вывод в терминал: [10, 22, 334, 4, 5, 6]
Содержимое списка
x
распаковано и помещено в список y
.Аргументы *args и **kwargs
Есть
случаи, когда неизвестно точное количество аргументов, которые будут
переданы в функцию. В таких случаях при объявлении функции вместо списка
аргументов применяют конструкцию
*args
или **kwargs
(или обе вместе).*args
— это сокращение от arguments (англ. «аргументы»), а **kwargs
— сокращение от keyword arguments (англ. «именованные аргументы»).Оператор
«звёздочка» в этих конструкциях используется для распаковки аргументов:
из них будет создана последовательность, которую можно обработать
внутри функции.
Скопировать кодPYTHON# В функции get_boost() первый аргумент - позиционный,
# а остальные будут распакованы в последовательность с именем ratings
def get_boost(coeff, *ratings):
for rating in ratings:
print(coeff + rating)
x = 0.2
# Вызываем функцию и передаём в неё шесть аргументов
# Первый аргумент будет передан в параметр coeff,
# а остальные будут преобразованы в последовательность
get_boost(x, 4.3, 4.5, 3.0, 2.5, 4.7)
# Вывод в терминал:
# 4.5
# 4.7
# 3.2
# 2.7
# 4.9
В примере используется имя
*ratings
, а не *args
, и в этом нет ошибки. args
— традиционное, но не обязательное имя для списка неименованных
аргументов. Главный трюк в этой конструкции — применение оператора
«звёздочка», а имя для последовательности можно задавать любое.В конструкции
**kwargs
имя kwargs
тоже не предустановлено, оно может быть любым. Оператор **
распаковывает именованные аргументы в словарь, и этот словарь можно обработать в теле функции:Скопировать кодPYTHONdef print_profile(character, **info):
print(f'Персонаж: {character}')
for key, value in info.items():
print(f'{key}: {value}')
print_profile('Spider-man',
name='Питер Паркер',
talent=['Суперсила', 'Паучье чутье', 'Паутина'],
sity='Нью-Йорк')
# Вывод в терминал:
# Персонаж: Spider-man
# name: Питер Паркет
# talent: ['Суперсила', 'Паучье чутье', 'Паутина']
# sity: Нью-Йорк
Пустая функция
При
построении структуры проекта разработчики часто создают пустые функции,
чтобы постепенно наполнять их кодом. Но если Python увидит функцию без
тела — он выдаст ошибку. Чтобы избежать этого, в тело функции ставят
«заглушку» — ключевое слово
pass
Скопировать кодPYTHONdef empty():
pass
Таким же образом можно применять многоточие
Ellipsis
:Скопировать кодPYTHONdef empty():
...
Пора применить полученные знания на практике. Вперед!
Функция
get_mean()
получает на вход список чисел. Напишите код функции так, чтобы она возвращала среднее арифметическое чисел из полученного списка.
Вызовите функцию
get_mean()
с аргументом num_lst
; напечатайте результат вызова, округлив его до двух знаков после запятой.КодPYTHON
10
1
def get_mean(values):
2
nums = 0
3
for num in values:
4
nums += num
5
return round(nums / len(values), 2)
6
7
# Список значений для теста
8
num_lst = [3, 6, 5, 7, 9, 1]
9
# Тут вызов функции.
10
print(get_mean(num_lst)) # Напечатайте результат вызова функции.
Функция принимает в качестве аргументов начальное и конечное значение диапазона и неопределённое количество чисел для проверки.
Напишите функцию, которая вернёт список чисел, попадающих в установленный диапазон.
Если значение находится вне диапазона функция должна печатать сообщение «Число за границами диапазона».
Допишите функцию
test_range()
так, чтобы она:- принимала в качестве аргументов
- начальное и конечное значение диапазона,
- неопределённое количество чисел для проверки;
- формировала список из чисел, которые попадают в установленный диапазон;
- для значений, которые находится вне пределов диапазона, печатала сообщение «Число за границами диапазона»;
- возвращала список чисел, попадающих в установленный диапазон.
КодPYTHON
13
1
def test_range(start, end, *args): # Укажите параметры
2
3
list_correct_number = []
4
for check_num in args:
5
if check_num not in range(start, end+1):
6
print(f'Число за границами диапазона')
7
else:
8
list_correct_number.append(check_num)
9
return list_correct_number
10
11
start = 4
12
end = 12
13
print(test_range(start, end, 5, 16, 32, 6, 7, 1))