Когда вам приходится повторять один и тот же код несколько раз в разных местах программы, это сигнализирует, что код нужно структурировать. Это делает ваш код более удобным для чтения, изменения и тестирования. В Python для этого есть функции.

Функции позволяют вам выполнить одну задачу один раз и затем переиспользовать её где угодно. Они помогают разделить код на небольшие логические блоки и не писать одно и то же несколько раз.

В этой статье мы разберём основы работы с функциями, а также применим их на реальной задаче.

Chatgpt image 5 дек. 2025 г., 17 25 54

Задача: создание системы для обработки студентов

Представьте, что у нас есть система для учёта студентов. У каждого студента есть:

  • имя
  • возраст
  • оценки по нескольким предметам

Наша задача — подсчитывать общую успеваемость студентов и делать отчёт о их успеваемости. Студент может получить разные оценки по разным предметам. Мы будем писать функции для:

  1. Подсчёта среднего балла.
  2. Определения, сдал ли студент экзамен (по усреднённой оценке).
  3. Подсчёта количества студентов, которые сдали все экзамены.

Пишем функции

Предположим, у нас есть данные о студентах:

students = [
    {"name": "John", "age": 21, "grades": {"math": 80, "english": 75, "physics": 90}},
    {"name": "Sarah", "age": 22, "grades": {"math": 95, "english": 88, "physics": 92}},
    {"name": "Mike", "age": 20, "grades": {"math": 60, "english": 65, "physics": 70}},
]

Каждый студент — это словарь, в котором:

  • name — имя студента,
  • age — возраст студента,
  • grades — словарь с оценками по предметам.

Функция 1: Подсчёт среднего балла

Для начала нам нужно посчитать среднюю оценку студента. Для этого напишем функцию, которая будет вычислять среднее значение оценок.

def calculate_average(grades):
    total = sum(grades.values())  # Суммируем все оценки
    return total / len(grades)    # Делим на количество предметов

Теперь можем посчитать средний балл для каждого студента:

for student in students:
    avg = calculate_average(student["grades"])
    print(f"{student['name']} - Средний балл: {avg:.2f}")

Результат будет таким:

John - Средний балл: 81.67
Sarah - Средний балл: 91.67
Mike - Средний балл: 65.00

Функция 2: Проверка, сдал ли студент

Следующий шаг: определить, сдал ли студент все экзамены. Для этого нам нужно подсчитать, сдал ли студент на достаточно высокий балл (например, >= 60).

def passed_all_exams(grades, passing_grade=60):
    return all(grade >= passing_grade for grade in grades.values())  # Проверяем, сдал ли каждый предмет

Используем её для проверки, сдал ли студент все экзамены:

for student in students:
    passed = passed_all_exams(student["grades"])
    result = "сдал" if passed else "не сдал"
    print(f"{student['name']} {result} все экзамены")

Результат:

John сдал все экзамены
Sarah сдал все экзамены
Mike не сдал все экзамены

Функция 3: Подсчёт количества студентов, которые сдали все экзамены

Теперь напишем функцию, которая будет подсчитывать количество студентов, сдавших все экзамены.

def count_students_passed_all(students):
    return sum(1 for student in students if passed_all_exams(student["grades"]))

Используем её для подсчёта:

passed_count = count_students_passed_all(students)
print(f"Количество студентов, сдавших все экзамены: {passed_count}")

Результат:

Количество студентов, сдавших все экзамены: 2

Именованные и позиционные аргументы

📢 Подписывайтесь на наш Telegram-канал.

Там вы найдете анонсы обучающих статей и видео, готовый код для ваших проектов и увлекательные курсы. Ничего лишнего — только практика, вдохновение и развитие.

👉 https://t.me/codelab_channel

Мы видим, что функции стали гибче благодаря использованию параметров. Но давайте рассмотрим, как можно работать с именованными и позиционными аргументами.

Позиционные аргументы — это когда параметры передаются в функции строго в том порядке, в котором они указаны.

def calculate_average(grades, passing_grade):
    # Позиционные аргументы: grades — оценки, passing_grade — проходной балл
    total = sum(grades.values())
    return total / len(grades)

В этом случае, когда вы вызываете функцию, важно передавать параметры в правильном порядке:

calculate_average(student["grades"], 60)

Именованные аргументы — это когда вы явно указываете, что где передаёте. Это делает код более читаемым и удобным:

calculate_average(grades=student["grades"], passing_grade=60)

Преимущество именованных аргументов в том, что можно передавать их в любом порядке:

calculate_average(passing_grade=60, grades=student["grades"])

Возвращение нескольких значений из функции

Иногда функции нужно возвращать больше одного значения. Например, мы можем захотеть не только посчитать средний балл, но и проверить, сдал ли студент все экзамены.

def calculate_average_and_passed(grades, passing_grade=60):
    average = sum(grades.values()) / len(grades)
    passed = all(grade >= passing_grade for grade in grades.values())
    return average, passed  # Возвращаем два значения

Используем:

for student in students:
    avg, passed = calculate_average_and_passed(student["grades"])
    result = "сдал" if passed else "не сдал"
    print(f"{student['name']} - Средний балл: {avg:.2f}, {result} все экзамены")

Результат:

John - Средний балл: 81.67, сдал все экзамены
Sarah - Средний балл: 91.67, сдал все экзамены
Mike - Средний балл: 65.00, не сдал все экзамены

Здесь мы вернули два значения: средний балл и результат по экзаменам, и распаковали их в переменные avg и passed.

Рекурсия: пример с вычислением суммы

Рекурсия — это когда функция вызывает саму себя. Для задач с повторяющимися подзадачами рекурсия может быть очень полезной.

Давайте попробуем использовать рекурсию для подсчёта общей суммы всех оценок у студента.

def calculate_total_recursive(grades):
    if not grades:  # Базовый случай: если список пуст, возвращаем 0
        return 0
    return grades[0] + calculate_total_recursive(grades[1:])

Для использования рекурсии нам нужно передавать список оценок:

grades_list = list(student["grades"].values())
total = calculate_total_recursive(grades_list)
print(f"Общая сумма оценок для {student['name']}: {total}")

Здесь рекурсия работает, добавляя оценки по одной и вызывая саму себя до тех пор, пока список не станет пустым.

Рекурсия должна иметь базовый случай (условие остановки), иначе вызовет бесконечную рекурсию и ошибку переполнения стека.

Заключение

Мы прошли через несколько важных аспектов работы с функциями:

  1. Объявление функции, параметры и возвращаемые значения — ключевые концепции для эффективного использования функций.
  2. Именованные и позиционные аргументы помогают сделать код более читаемым и гибким.
  3. Мы научились возвращать несколько значений из функции.
  4. Рекурсия может быть полезна для решения задач, которые повторяются (например, подсчёт суммы).

Функции позволяют избавиться от дублирования кода и повысить читаемость программы. Следующий шаг — это углубление в более сложные структуры данных и работу с более сложными параметрами в функциях.

Практика на том же примере

  1. Добавьте функцию, которая будет возвращать список студентов, чьи средние баллы выше определённого значения.
  2. Реализуйте функцию, которая будет вычислять, сколько студентов сдали экзамены, если балл больше заданного порога.
  3. Измените функцию calculate_average_and_passed, чтобы она возвращала не только средний балл, но и список предметов, по которым студент не сдал экзамен.

Эти задачи заставят вас эффективно работать с функциями, улучшая ваши навыки в их использовании и расширяя возможности для реальных приложений.