Можно ли в Python задать дефолтное значение аргумента функции списком и какие проблемы это может вызвать
Что проверяют
Знаете ли вы, когда Python вычисляет значения по умолчанию, и понимаете ли разницу между изменяемыми и неизменяемыми объектами. Следом обычно показывают код и просят предсказать вывод второго вызова или найти ту же ошибку в dataclass.
Как отвечать
Задать список по умолчанию можно, синтаксис это разрешает. Проблема в моменте вычисления: выражение [] выполняется один раз, при определении функции, а не при каждом вызове. Объект хранится в func.__defaults__, и все вызовы без этого аргумента получают один и тот же список. Функция add(x, acc=[]), которая делает acc.append(x), на втором вызове add(2) вернёт [1, 2], а не [2].
Стандартное решение: None как значение по умолчанию и создание списка внутри функции через if acc is None: acc = [].
В работе с данными это всплывает чаще, чем кажется:
- функции подготовки признаков:
def build_features(df, cols=[]), где список колонок растёт от вызова к вызову, и модели на разных прогонах учатся на разных наборах; - конфиги: словарь гиперпараметров по умолчанию, который кто-то дополнил внутри функции;
dataclass: изменяемый дефолт поля запрещён и падает сValueError, правильный вариантfield(default_factory=list). В Pydantic используютField(default_factory=list).
Та же ловушка у любого выражения в дефолте: ts=datetime.now() навсегда запомнит время загрузки модуля. Ловят это линтеры: правило B006 в Ruff и flake8-bugbear, dangerous-default-value в pylint.
Иногда поведение используют намеренно, как самодельный кэш между вызовами, но для этого есть functools.lru_cache, и читать его проще.
Где спотыкаются
Считают, что список создаётся заново при каждом вызове, и объясняют разный вывод «багом интерпретатора».
Исправляют через acc = acc or []. Если вызывающий передал свой пустой список, функция молча создаст новый и не изменит переданный.
Уверены, что проблема только у списков. С dict, set и пользовательскими объектами всё то же самое, безопасны лишь неизменяемые значения вроде чисел, строк и кортежей из неизменяемых элементов.