Функции в Python: пишем один раз, используем много раз

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


Как объявить функцию

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

python
def приветствие(имя):
    print(f"Привет, {имя}!")

Вызов:

python
приветствие("Анна")
приветствие("Борис")

Вывод:

text
Привет, Анна!
Привет, Борис!

Здесь логика «напечатать приветствие» описана один раз, но используется дважды.


Возврат значения: return

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

python
def квадрат(x):
    return x * x

Использование:

python
a = квадрат(3)
b = квадрат(5)
print(a, b)

Вывод:

text
9 25

Теперь результат можно сохранять в переменные, передавать в другие функции, складывать и т. д.


Параметры по умолчанию

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

python
def формат_цены(сумма, валюта="руб."):
    return f"{сумма} {валюта}"

Примеры вызова:

python
print(формат_цены(100))
print(формат_цены(200, "USD"))

Вывод:

text
100 руб.
200 USD

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


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

При вызове можно передавать аргументы по порядку (позиционно) или по имени.

python
def создать_заказ(товар, количество, статус="новый"):
    return f"Заказ: {количество} шт. {товар}, статус: {статус}"

Варианты вызова:

python
# Позиционные
print(создать_заказ("кофе", 3))
 
# Именованные (порядок не важен)
print(создать_заказ(количество=2, товар="чай", статус="в обработке"))

Вывод:

text
Заказ: 3 шт. кофе, статус: новый
Заказ: 2 шт. чай, статус: в обработке

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


Переменное число аргументов: *args и **kwargs

Когда заранее неизвестно, сколько значений передадут, используют *args (кортеж аргументов) и **kwargs (словарь именованных аргументов).

*args — список значений

python
def сумма_всех(*числа):
    total = 0
    for n in числа:
        total += n
    return total

Вызовы:

python
print(сумма_всех(1, 2, 3))
print(сумма_всех(10, 20, 30, 40))

Вывод:

text
6
100

**kwargs — именованные параметры

python
def показать_настройки(**настройки):
    for ключ, значение in настройки.items():
        print(f"{ключ}: {значение}")

Вызов:

python
показать_настройки(тема="тёмная", шрифт="14px", язык="ru")

Вывод:

text
тема: тёмная
шрифт: 14px
язык: ru

На практике *args и **kwargs чаще всего используют, когда пишут утилиты, декораторы или обёртки над другими функциями.


Практический пример: функция для валидации возраста

Допустим, нужно проверять, что возраст находится в диапазоне 0–120. Эту проверку придётся делать в разных местах — лучше вынести в функцию.

python
def проверить_возраст(возраст):
    if not isinstance(возраст, int):
        return False, "Возраст должен быть целым числом"
    if возраст < 0 or возраст > 120:
        return False, "Возраст вне допустимого диапазона (0–120)"
    return True, "OK"

Использование в разных местах:

python
ok, сообщение = проверить_возраст(25)
if ok:
    print("Возраст корректен")
else:
    print("Ошибка:", сообщение)
 
ok2, сообщение2 = проверить_возраст(-5)
if not ok2:
    print("Ошибка:", сообщение2)

Вывод:

text
Возраст корректен
Ошибка: Возраст вне допустимого диапазона (0120)

Логика проверки написана один раз, а используется в нескольких местах. Если позже диапазон изменится, достаточно поправить код в одном месте.


Частые ошибки и как их избежать

  • Забыли return, а ждут результат.
    Функция без return возвращает None.

    python
    def удвоить(x):
        x * 2          # результат никуда не сохраняется и не возвращается
     
    r = удвоить(5)     # r будет None

    Правильно:

    python
    def удвоить(x):
        return x * 2
  • Изменяемые объекты как параметры по умолчанию.
    Не делайте так:

    python
    def добавить_элемент(элемент, список=[]):
        список.append(элемент)
        return список

    Список [] создаётся один раз при определении функции, и между вызовами он «помнит» предыдущие элементы.
    Правильный вариант:

    python
    def добавить_элемент(элемент, список=None):
        if список is None:
            список = []
        список.append(элемент)
        return список

Пример: функция для расчёта скидки

Задача: посчитать итоговую цену с учётом скидки в процентах. Скидка может отсутствовать, тогда она равна 0.

python
def итоговая_цена(базовая, скидка_проц=0):
    скидка = базовая * скидка_проц / 100
    return базовая - скидка

Вызовы:

python
print(итоговая_цена(1000))           # без скидки
print(итоговая_цена(1000, 10))       # скидка 10%
print(итоговая_цена(2500, скидка_проц=20))  # именованный аргумент

Вывод:

text
1000.0
900.0
2000.0

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


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

  • Если один и тот же фрагмент встречается в двух и более местах — вынесите в функцию.
  • Если блок кода решает понятную подзадачу (проверка, форматирование, расчёт) — функция сделает его смысл яснее.
  • Если позже может понадобиться изменить логику — функция позволит сделать это в одном месте, а не править код по всему проекту.

Вывод

Функции позволяют:

  • не дублировать код;
  • делать логику понятнее за счёт осмысленных имён;
  • менять поведение в одном месте вместо правки во многих;
  • переиспользовать готовые решения в разных задачах.

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

Добавить комментарий