Python: уроки, справочник и задачи

Практические задачи по функциям Python с разбором

Раздел: Задачи на Python с решениями · Обновлено 31.10.2026

Практические задачи по функциям Python в этом блоке учат объявлять функции через def и lambda, передавать аргументы, возвращать результат и вызывать функцию из самой себя. Каждая задача дана с условием, решением на Python 3 и разбором, на что обратить внимание. Последние три задачи новые, их стоит решить без подсказок.

Практические задачи по функциям Python с разбором
Фото: Ezalvarenga / CC BY 3.0, Wikimedia Commons
Содержание статьи
  1. Что повторить перед решением
  2. Задача 1. Степени двойки через lambda и map
  3. Задача 2. Числа, кратные заданному
  4. Задача 3. Калькулятор на функциях
  5. Задача 4. Календарь на заданный месяц
  6. Задача 5. Числа Фибоначчи рекурсией
  7. Новые задачи для самостоятельного решения
    1. Задача 6. Проверка простого числа
    2. Задача 7. Среднее любого количества чисел
    3. Задача 8. Ловушка изменяемого аргумента
  8. Частые вопросы
    1. Чем lambda отличается от обычной функции def?
    2. Почему функция возвращает None?
    3. Какая максимальная глубина рекурсии в Python?
    4. Когда выносить код в отдельную функцию?

Что повторить перед решением

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

Главное правило для всех задач: функция должна возвращать значение через return, а печатать результат лучше снаружи. Такую функцию легко проверить и переиспользовать в другой программе.

Задача 1. Степени двойки через lambda и map

Выведите степени числа 2 от нулевой до девятой. Список значений нужно получить одной строкой с помощью map() и lambda-функции, а печать сделать в цикле.

Решение:

terms = 10
result = list(map(lambda x: 2 ** x, range(terms)))

print('Всего степеней:', terms)
for i, value in enumerate(result):
    print(f'2 в степени {i} равно {value}')

Функция map() применяет lambda к каждому числу из range(10) и возвращает ленивый итератор, поэтому его оборачивают в list(). Функция enumerate() выдает пары (индекс, значение) и избавляет от обращения result[i].

Тот же список проще записать генератором списка: [2 ** x for x in range(terms)]. В новом коде такой вариант встречается чаще, а map() удобен, когда функция уже есть готовая, например map(str, numbers).

Доработка для самостоятельной практики: пусть пользователь вводит основание и последнюю степень, а вывод выравнивается по столбцам через f-строку {value:>6}.

Задача 2. Числа, кратные заданному

Дан список целых чисел. Найдите все числа, которые делятся на 13 без остатка, используя filter() и lambda-функцию.

Решение:

my_list = [12, 65, 54, 39, 102, 339, 221]
result = list(filter(lambda x: x % 13 == 0, my_list))
print('Числа, кратные 13:', result)
# Числа, кратные 13: [65, 39, 221]

Функция filter() оставляет только те элементы, для которых lambda вернула True. Число 339 в результат не попало: 339 = 13 * 26 + 1.

Чтобы делитель не был зашит в код, оформите решение функцией с параметром:

def multiples(numbers, k):
    return [n for n in numbers if n % k == 0]

print(multiples([10, 15, 22, 30], 5))  # [10, 15, 30]

Задача 3. Калькулятор на функциях

Напишите калькулятор на четыре действия. Каждое действие оформите отдельной функцией, программа спрашивает номер операции и два числа, при неверном вводе повторяет вопрос. Деление на ноль не должно ронять программу.

Решение:

def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    if y == 0:
        return 'ошибка: деление на ноль'
    return x / y

operations = {'1': ('+', add), '2': ('-', subtract),
              '3': ('*', multiply), '4': ('/', divide)}

print('1 - сложить, 2 - вычесть, 3 - умножить, 4 - делить')
while True:
    choice = input('Выберите действие (1/2/3/4): ')
    if choice in operations:
        break
    print('Неправильный ввод')

num1 = float(input('Первое число: '))
num2 = float(input('Второе число: '))
sign, func = operations[choice]
print(num1, sign, num2, '=', func(num1, num2))

Пример работы:

Выберите действие (1/2/3/4): 2
Первое число: 100
Второе число: 20
100.0 - 20.0 = 80.0

Вместо цепочки if/elif функции сложены в словарь: ключ - номер операции, значение - кортеж из знака и самой функции. В Python функция является обычным объектом, ее можно положить в словарь и вызвать позже. Добавить пятую операцию, например возведение в степень, теперь можно одной строкой.

Задача 4. Календарь на заданный месяц

Пользователь вводит год и номер месяца, программа печатает календарь этого месяца. Используйте стандартный модуль calendar.

Решение:

import calendar

yy = int(input('Год: '))
mm = int(input('Месяц (1-12): '))
print(calendar.month(yy, mm))

Результат для марта 2025 года:

     March 2025
Mo Tu We Th Fr Sa Su
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

Функция calendar.month() возвращает готовую многострочную строку, неделя начинается с понедельника. Если ввести месяц 13, модуль выбросит IllegalMonthError, поэтому в полной версии стоит проверить диапазон 1-12. Для дат в других задачах пригодится модуль datetime.

Задача 5. Числа Фибоначчи рекурсией

Напишите рекурсивную функцию, которая возвращает n-е число Фибоначчи, и выведите первые 10 чисел последовательности. Каждое число равно сумме двух предыдущих, а первые два равны 0 и 1.

Решение:

def recur_fibo(n):
    if n <= 1:
        return n
    return recur_fibo(n - 1) + recur_fibo(n - 2)

nterms = 10
print('Последовательность Фибоначчи:')
for i in range(nterms):
    print(recur_fibo(i), end=' ')
# 0 1 1 2 3 5 8 13 21 34

Условие n <= 1 - базовый случай, без него рекурсия ушла бы в минус бесконечность и закончилась ошибкой RecursionError. У такого решения есть недостаток: одни и те же значения считаются много раз, и уже recur_fibo(35) работает несколько секунд.

Исправить это можно кешем из модуля functools: декоратор запоминает результаты вызовов, и каждое число считается один раз.

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    return n if n <= 1 else fib(n - 1) + fib(n - 2)

print(fib(80))  # 23416728348467685

Новые задачи для самостоятельного решения

Эти три задачи проверяют, насколько уверенно получается писать функции без подсказок. Решение каждой занимает 5-10 строк.

Задача 6. Проверка простого числа

Напишите функцию is_prime(n), которая возвращает True для простого числа и False для остальных. Делители достаточно перебирать до квадратного корня из n.

Решение:

def is_prime(n):
    if n < 2:
        return False
    for d in range(2, int(n ** 0.5) + 1):
        if n % d == 0:
            return False
    return True

print([x for x in range(20) if is_prime(x)])
# [2, 3, 5, 7, 11, 13, 17, 19]

Задача 7. Среднее любого количества чисел

Напишите функцию average(), которая принимает любое число аргументов и возвращает их среднее, округленное до двух знаков. Без аргументов функция возвращает 0.

Решение:

def average(*numbers):
    if not numbers:
        return 0
    return round(sum(numbers) / len(numbers), 2)

print(average(4, 5, 5))  # 4.67
print(average())         # 0

Звездочка перед параметром собирает все позиционные аргументы в кортеж numbers.

Задача 8. Ловушка изменяемого аргумента

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

def add_item(item, items=[]):
    items.append(item)
    return items

print(add_item(1))  # [1]
print(add_item(2))  # [1, 2]

Решение:

def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

Значение по умолчанию вычисляется один раз, при объявлении функции, поэтому все вызовы делят один и тот же список. Для изменяемых типов (список, словарь, множество) по умолчанию ставят None и создают объект внутри функции.

Частые вопросы

Ответы на вопросы, которые чаще всего возникают при решении задач на функции.

Чем lambda отличается от обычной функции def?

Lambda записывается в одну строку, не имеет имени и может содержать только одно выражение, результат которого возвращается автоматически. Функция через def может включать любые операторы, документацию и несколько return. Lambda удобна как короткий аргумент для map(), filter() или sorted(key=...).

Почему функция возвращает None?

Значит, в ней нет оператора return или выполнение до него не дошло. Частая ошибка новичков - вызвать print() внутри функции вместо return и потом пытаться сохранить результат в переменную.

Какая максимальная глубина рекурсии в Python?

По умолчанию около 1000 вызовов, точное значение возвращает sys.getrecursionlimit(). Лимит можно поднять через sys.setrecursionlimit(), но для глубоких вычислений надежнее переписать функцию на цикл.

Когда выносить код в отдельную функцию?

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