Представь, что ты пишешь программу, которая здоровается с пользователем, говорит сколько букв в его имени и выводит первую букву заглавной. Вот как это выглядит:
name = "anna"
print("Привет, " + name + "!")
print("В твоём имени " + str(len(name)) + " буквы")
print("Первая буква: " + name[0].upper())Теперь представь, что нужно сделать то же самое для трёх разных пользователей:
name = "anna"
print("Привет, " + name + "!")
print("В твоём имени " + str(len(name)) + " буквы")
print("Первая буква: " + name[0].upper())
name = "ivan"
print("Привет, " + name + "!")
print("В твоём имени " + str(len(name)) + " буквы")
print("Первая буква: " + name[0].upper())
name = "maria"
print("Привет, " + name + "!")
print("В твоём имени " + str(len(name)) + " буквы")
print("Первая буква: " + name[0].upper())Код раздулся. И если понадобится что-то исправить — придётся менять в трёх местах. А если пользователей будет сто?
Функция решает эту проблему. Мы один раз описываем действие, даём ему имя — и затем просто вызываем это действие столько раз, сколько нужно.
Думай о функции как о глаголе, который ты сам придумал. В языке есть print(), len(), input() — это глаголы, встроенные в Python. Функция позволяет тебе добавить свой глагол: greet(), calculate(), check().
def greet(name):
print("Привет, " + name + "!")
print("В твоём имени " + str(len(name)) + " буквы")
print("Первая буква: " + name[0].upper())Разберём синтаксис:
def— ключевое слово, означает «я определяю функцию»greet— имя функции (ты придумываешь сам)(name)— параметр: переменная, которую функция получит при вызове:— двоеточие обязательно- всё, что внутри — тело функции, пишется с отступом
Теперь вызвать её можно вот так:
greet("anna")
greet("ivan")
greet("maria")Три строки вместо двенадцати. И если нужно что-то изменить — меняем только в одном месте.
Параметр — это переменная, которая существует только внутри функции. Снаружи её нет.
Представь функцию как кухню, а параметры — как ингредиенты, которые ты туда приносишь. Что происходит на кухне — остаётся на кухне. Магазин, где ты купил продукты, об этом не знает.
def square(number):
result = number * number
print(result)
square(5) # выведет 25
square(3) # выведет 9
square(10) # выведет 100Переменная number существует только пока работает функция. После — исчезает. Ты не можешь написать print(number) снаружи и получить что-то осмысленное.
Функция может принимать несколько параметров:
def introduce(name, age):
print("Меня зовут " + name + ", мне " + str(age) + " лет")
introduce("Анна", 20)
introduce("Иван", 25)Параметры передаются по порядку: первый аргумент идёт в первый параметр, второй — во второй.
До этого функции что-то делали (печатали на экран). Но часто функция должна что-то посчитать и отдать результат — чтобы его можно было использовать дальше.
Сравни два варианта:
# Функция просто печатает — результат нельзя использовать дальше
def add_print(a, b):
print(a + b)
# Функция возвращает результат — его можно сохранить и использовать
def add_return(a, b):
return a + bРазница становится очевидной, когда нужно что-то сделать с результатом:
result = add_return(3, 5) # сохранили результат
print(result * 2) # можем использовать дальше — выведет 16
# А вот это не сработает так, как ожидаешь:
result = add_print(3, 5) # add_print ничего не возвращает
print(result * 2) # result будет None — ошибкаПравило: если функция должна что-то вычислить — используй return. Если она просто выводит информацию — можно обойтись print внутри.
Настоящая сила return раскрывается, когда задачу нужно разбить на части.
Задача: посчитать итоговую стоимость покупки с учётом скидки и налога.
Разобьём на подзадачи:
- Посчитать сумму скидки
- Посчитать сумму налога
- Посчитать итоговую цену
- Вывести чек
def calculate_discount(price, percent):
return price * percent / 100
def calculate_tax(price, rate):
return price * rate / 100
def calculate_total(price, discount, tax):
return price - discount + tax
def print_receipt(price, discount, tax, total):
print("Цена: " + str(price) + " руб.")
print("Скидка: -" + str(discount) + " руб.")
print("Налог: +" + str(tax) + " руб.")
print("Итого: " + str(total) + " руб.")
# Используем все функции вместе
price = 1000
discount = calculate_discount(price, 10) # 10% скидка
tax = calculate_tax(price, 5) # 5% налог
total = calculate_total(price, discount, tax)
print_receipt(price, discount, tax, total)Обрати внимание на разделение обязанностей:
calculate_discount,calculate_tax,calculate_total— только считают, ничего не печатают. Они используютreturn.print_receipt— только выводит, ничего не считает. В ней нетreturn.
Это делает код понятным: каждая функция делает одно дело.
Ещё один пример декомпозиции: проверка регистрации пользователя.
Условия: возраст не меньше 18, имя не пустое, пароль не короче 6 символов.
def is_adult(age):
return age >= 18
def has_name(name):
return len(name) > 0
def has_valid_password(password):
return len(password) >= 6
def can_register(name, age, password):
if not is_adult(age):
return False
if not has_name(name):
return False
if not has_valid_password(password):
return False
return True
# Проверяем
print(can_register("Анна", 20, "qwerty")) # True
print(can_register("", 20, "qwerty")) # False — нет имени
print(can_register("Иван", 15, "qwerty")) # False — не совершеннолетний
print(can_register("Мария", 22, "123")) # False — слабый парольКаждая маленькая функция проверяет одно условие. Итоговая функция can_register просто собирает их вместе. Читать и отлаживать такой код гораздо проще.
Напиши функцию, которая:
- Принимает имя и выводит приветствие:
"Привет, Анна!" - Принимает число и возвращает его квадрат
- Принимает количество минут и возвращает количество секунд
- Принимает число и возвращает
True, если оно чётное, иFalseесли нечётное - Принимает два числа и возвращает их сумму
- Принимает число и возвращает его абсолютное значение (без использования
abs()) - Принимает температуру в Цельсиях и возвращает её в Фаренгейтах (
F = C * 9/5 + 32) - Принимает строку и возвращает её длину
- Принимает два числа и возвращает наибольшее из них (без
max()) - Принимает имя и возвращает его заглавными буквами
Напиши функцию, которая:
- Принимает два числа и возвращает их разность по модулю (всегда положительную)
- Принимает возраст и возвращает строку:
"ребёнок"(до 12),"подросток"(12–17),"взрослый"(18+) - Принимает число и делитель, возвращает
Trueесли число делится на делитель без остатка - Принимает три числа — цену, количество и скидку в процентах — и возвращает итоговую стоимость
- Принимает строку и возвращает
Trueесли она начинается с заглавной буквы - Принимает два числа и возвращает
"больше","меньше"или"равно"(второе относительно первого) - Принимает число секунд и возвращает строку в формате
"MM:СС"(например,"02:05") - Принимает имя пользователя и пароль, возвращает
Trueесли имя не пустое и пароль длиннее 5 символов - Принимает скорость и время, возвращает расстояние. Если скорость или время отрицательные — возвращает
0 - Принимает оценку (число от 1 до 100) и возвращает букву:
A(90–100),B(75–89),C(60–74),D(ниже 60)
Напиши функцию, которая:
- Принимает строку и возвращает количество слов в ней
- Принимает список чисел и возвращает их среднее значение
- Принимает список чисел и возвращает новый список, содержащий только чётные числа
- Принимает строку и символ, возвращает количество вхождений этого символа в строку (без
count()) - Принимает список строк и возвращает самую длинную строку
- Принимает предложение и возвращает его слова в обратном порядке (как список)
- Принимает словарь
{"имя": оценка}и возвращает имя студента с наибольшей оценкой - Принимает список чисел и возвращает словарь:
{"min": ..., "max": ..., "sum": ..., "avg": ...} - Принимает строку и возвращает
Trueесли она является палиндромом (читается одинаково в обоих направлениях). Регистр игнорировать. - Принимает список словарей вида
{"name": "Анна", "age": 20}и возвращает новый список, отфильтрованный по минимальному возрасту, который тоже передаётся как параметр