Значения по умолчанию

Значения по умолчанию

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

Синтаксис значений по умолчанию

Значение по умолчанию задаётся знаком = прямо в определении функции:

def greet(name, greeting="Привет"):
    print(f"{greeting}, {name}!")

greet("Алиса")             # Привет, Алиса!  — greeting использует default
greet("Борис", "Здравствуй")  # Здравствуй, Борис!  — default переопределён
greet("Вера", greeting="Добрый день")  # именованный аргумент

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

Правило порядка: обязательные параметры идут первыми

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

# OK: сначала обязательные, потом с дефолтом
def connect(host, port=5432, timeout=30):
    print(f"Подключение к {host}:{port}, таймаут {timeout}с")

connect("localhost")               # host="localhost", port=5432, timeout=30
connect("db.example.com", 3306)    # port=3306, timeout=30
connect("db.example.com", timeout=60)  # port=5432, timeout=60

# ОШИБКА: обязательный параметр ПОСЛЕ необязательного
# def wrong(port=5432, host):   # SyntaxError
#     pass

Типичные сценарии применения

Значения по умолчанию особенно полезны там, где большинство вызовов предполагают «стандартный» режим работы:

def log(message, level="INFO", timestamp=True):
    prefix = "[INFO]" if level == "INFO" else f"[{level}]"
    if timestamp:
        import datetime
        t = datetime.datetime.now().strftime("%H:%M:%S")
        print(f"{t} {prefix} {message}")
    else:
        print(f"{prefix} {message}")

log("Сервер запущен")                        # стандартный лог с временем
log("Диск заполнен на 90%", level="WARNING") # предупреждение
log("Тест", timestamp=False)                 # без временной метки

Функция log() удобна в обоих вариантах: простом и детальном, — без необходимости передавать все параметры каждый раз.

Опасная ловушка: изменяемые значения по умолчанию

Вот одна из самых распространённых ошибок в Python. Никогда не используйте изменяемые объекты ([], {}, set()) в качестве значений по умолчанию:

# ПЛОХО — дефолтный список создаётся ОДИН РАЗ при определении функции:
def append_item(item, lst=[]):
    lst.append(item)
    return lst

print(append_item(1))   # [1]
print(append_item(2))   # [1, 2]  — ожидали [2], но список сохранился!
print(append_item(3))   # [1, 2, 3]

Проблема в том, что значение по умолчанию [] создаётся однажды — при загрузке определения функции. Все вызовы без явного lst используют один и тот же объект списка.

Правильный паттерн — использовать None как часовой:

# ХОРОШО — новый список создаётся при каждом вызове:
def append_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

print(append_item(1))   # [1]
print(append_item(2))   # [2]  — теперь каждый раз новый список

Это стандартный Python-идиом. Запомните его: для изменяемых дефолтов — None + проверка внутри функции.

Когда задавать значения по умолчанию

Хорошие кандидаты для дефолтных значений:

  • Флаги включения/выключения опции (verbose=False, dry_run=False)
  • Типичные настройки (timeout=30, encoding="utf-8")
  • Пустые коллекции — только через None-паттерн
  • Форматирование по умолчанию (sep=" ", end="\n" в print)

Не добавляйте дефолты «на всякий случай». Если параметр всегда должен передаваться явно — оставьте его обязательным. Дефолт уместен, когда для большинства вызовов «стандартное» значение очевидно.

Проверь себя

Что выведет следующий код?

def power(base, exp=2):
    return base ** exp

print(power(3))
print(power(3, 3))
print(power(exp=4, base=2))
  • power(3)3 ** 29
  • power(3, 3)3 ** 327
  • power(exp=4, base=2)2 ** 416

Итог

  • def f(a, b=10):b необязателен; при вызове без него подставляется 10.
  • Обязательные параметры всегда стоят перед необязательными.
  • Никогда не используйте [] или {} как дефолт — используйте None и создавайте внутри функции.
  • Дефолты — это контракт: «если не сказали иначе, работаем вот так».

В следующем уроке изучим *args и **kwargs — механизм для функций с переменным числом аргументов.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике