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

Содержание статьи
Что повторить перед решением
Для задач понадобятся базовые конструкции: циклы, условия и списки. Если какая-то тема пока дается с трудом, сначала прочитайте теорию по ссылкам ниже, иначе разбор решений будет казаться набором заклинаний.
- объявление функций,
returnи область видимости; - позиционные и именованные аргументы, значения по умолчанию,
*args; - анонимные lambda-функции и встроенные
map(),filter(); - рекурсия и базовый случай.
Главное правило для всех задач: функция должна возвращать значение через 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(), но для глубоких вычислений надежнее переписать функцию на цикл.
Когда выносить код в отдельную функцию?
Когда один и тот же фрагмент повторяется два раза и больше или когда блок кода решает отдельную подзадачу, которую можно назвать одним глаголом: посчитать, проверить, загрузить. Короткие функции проще тестировать и читать.