Глава 13 · Автоматизация с помощью функций

Нет аргументов? Слишком много аргументов!

Значения по умолчанию делают аргумент необязательным — но изменяемое значение по умолчанию скрывает одну из самых известных ловушек Python.

Нет аргументов? Что делать!

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

znachenie_po_umolchaniyu.py
def privetstvie(imya="друг"):
    print(f"Привет, {imya}!")

privetstvie()          # Привет, друг!
privetstvie("Ада")     # Привет, Ада!
СигнатураРоль
imyaобязательный параметр — если бы не было умолчания
imya="друг"необязательный параметр со значением по умолчанию

Ловушка изменяемого значения по умолчанию

Это один из самых известных сюрпризов Python — и его нужно разобрать не торопясь.

mutable_default_trap.py
def add_task(task, tasks=[]):
    tasks.append(task)
    return tasks

print(add_task("A"))
print(add_task("B"))
['A']
['A', 'B']
Второй вызов не начинает с пустого списка — B добавился к тому же списку, что и A!
Список по умолчанию создаётся ОДИН РАЗ — когда выполняется def
tasks=[] вычисляется в момент определения функции, а не заново при каждом вызове. Получается один и тот же список-объект по умолчанию, общий для всех вызовов, где аргумент не передан явно.
ОСНОВНАЯ ПРОГРАММАФУНКЦИЯ (на этапе определения)def add_task(task,tasks=[]):создаётся список-объектпо умолчанию []вызов
Список по умолчанию создаётся один раз, когда Python выполняет саму строку def
Вызов 1:add_task('A')Вызов 2:add_task('B')ОДИН И ТОТ ЖЕсписок по…
Оба вызова без явного tasks используют один и тот же общий список

Правильный паттерн: None как отметка «не передано»

mutable_default_fix.py
def add_task(task, tasks=None):
    if tasks is None:
        tasks = []

    tasks.append(task)
    return tasks
None — безопасный сигнальный аргумент по умолчанию
None — неизменяемый одиночный объект, поэтому его можно безопасно использовать как значение по умолчанию. Проверка if tasks is None (глава 9: is None) создаёт НОВЫЙ пустой список при каждом вызове без аргумента — ровно то поведение, которое интуитивно ожидалось. Это не единственный способ решить проблему, но самый распространённый.

Слишком много аргументов!

Иногда заранее неизвестно, сколько аргументов понадобится передать. Символ * перед именем параметра собирает любое количество аргументов в один кортеж (глава 11):

args.py
def summa_vseh(*chisla):
    itog = 0
    for n in chisla:
        itog += n
    return itog

print(summa_vseh(1, 2))           # 3
print(summa_vseh(1, 2, 3, 4, 5))  # 15 — сколько угодно аргументов
Именованные аргументы — напоминание
Аргументы можно передавать и по имени, а не только по порядку: privetstvie(imya="Ада") — подробнее об этом в §13.6.
Практика: значения по умолчанию и ловушка изменяемого умолчания
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →